Commit 92216d28 authored by zhangfangli's avatar zhangfangli

上传图片丢失问题

parent 3db27e8d
Pipeline #16618 canceled with stage
......@@ -9,9 +9,11 @@ tags:
author: 张芳利
---
<a name="XDoI3"></a>
## 一、什么是跨域
要知道什么是跨域,需要先知道另一个名词【**同源政策**】。<br />同源政策:是一个重要的安全政策,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。<br />而什么才是同源呢?同源就是两个页面具有相同的协议,域名和端口 均一致。所以根据上面的了解,**源=协议+主机/域名+端口,当源不同的时候也就是跨域了**<br />例如:<br />
要知道什么是跨域,需要先知道另一个名词【**同源政策**】。
同源政策:是一个重要的安全政策,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
而什么才是同源呢?同源就是两个页面具有相同的协议,域名和端口 均一致。所以根据上面的了解,**源=协议+主机/域名+端口,当源不同的时候也就是跨域了**
例如:
![crossDomain](/yifu-study-front-share/images/crossDomain/img1.png)
| **当前页面url** | **被请求页面url** | **是否跨域** | **原因** |
......@@ -25,24 +27,26 @@ author: 张芳利
**注意:**
> 在默认情况下 http 可以省略端口 80, https 省略 443。
<a name="C9fUE"></a>
## 二、跨域的限制
- Cookie,LocalStorage,IndexDB 等存储性内容无法读取
- DOM 节点无法访问
- Ajax 请求发出去了,但是响应被浏览器拦截了
基本我们说的跨域是在第三点请求上面。<br />ajax请求报错:
基本我们说的跨域是在第三点请求上面。
ajax请求报错:
```jsx
Access to XMLHttpRequest at 'xxx' from origin 'xxx' has been block by CORS,
policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```
<a name="HSQ39"></a>
## 三、解决跨域
<a name="uTL8Z"></a>
### 方法一:JSONP
JSONP 是 JSON with Padding 的缩写,主要就是利用了 script 标签没有跨域限制的这个特性来完成的。<br />**思路:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。**<br />缺点:只支持get请求,不支持post请求。<br />(下面的接口都是聚合数据里面的免费接口,如果想实验测试一下可以自己更换一下接口地址哈~)<br />**1、原生js**
JSONP 是 JSON with Padding 的缩写,主要就是利用了 script 标签没有跨域限制的这个特性来完成的。
**思路:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。**
缺点:只支持get请求,不支持post请求。
(下面的接口都是聚合数据里面的免费接口,如果想实验测试一下可以自己更换一下接口地址哈~)
**1、原生js**
```jsx
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
......@@ -67,7 +71,8 @@ script>
type="text/javascript"
>script>
```
**2、vue.js ** <br />2.1 安装jsonp,利用jsonp插件
**2、vue.js **
2.1 安装jsonp,利用jsonp插件
```jsx
yarn add jsonp
......@@ -160,9 +165,12 @@ export const getTest = () => {
}
```
<a name="LNDy8"></a>
### 方法二:CORS
CORS是基于http1.1的一种跨域解决方案,它的全称是**C**ross-**O**rigin **R**esource **S**haring,跨域资源共享。<br />**思路:如果浏览器要跨域访问服务器的资源,需要获得服务器的允许**<br />缺点:当你使用 IE<=9, Opera<12, or Firefox<3.5 或者更加老的浏览器,就不适合 <br />在 cors 中会有 简单请求 和 复杂请求的概念。简单请求:当请求**同时满足**以下条件时,浏览器会认为它是一个简单请求:<br />情况一: 使用以下方法(意思就是以下请求意外的都是非简单请求)
CORS是基于http1.1的一种跨域解决方案,它的全称是**C**ross-**O**rigin **R**esource **S**haring,跨域资源共享。
**思路:如果浏览器要跨域访问服务器的资源,需要获得服务器的允许**
缺点:当你使用 IE<=9, Opera<12, or Firefox<3.5 或者更加老的浏览器,就不适合
在 cors 中会有 简单请求 和 复杂请求的概念。简单请求:当请求**同时满足**以下条件时,浏览器会认为它是一个简单请求:
情况一: 使用以下方法(意思就是以下请求意外的都是非简单请求)
- GET
- HEAD
......@@ -186,7 +194,10 @@ CORS是基于http1.1的一种跨域解决方案,它的全称是**C**ross-**O**
- multipart/form-data
- application/x-www-form-urlencoded
情况四:<br />请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。<br />情况五:<br />请求中没有使用 ReadableStream 对象。
情况四:
请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
情况五:
请求中没有使用 ReadableStream 对象。
```jsx
// 简单请求
fetch('http://crossdomain.com/api/news');
......@@ -219,7 +230,9 @@ fetch('http://crossdomain.com/api/news', {
```
不满足上面的就是复杂请求。一般CORS的设置都是在后端的。
**1、**普通跨域请求:只需服务器端设置Access-Control-Allow-Origin<br />2、带cookie跨域请求:前后端都需要进行设置<br />**【前端设置】根据xhr.withCredentials字段判断是否带有cookie**
**1、**普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置
**【前端设置】根据xhr.withCredentials字段判断是否带有cookie**
```jsx
// 原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
......@@ -258,9 +271,9 @@ axios.defaults.withCredentials = true
```
<a name="EBefT"></a>
### 方法三:代理
**思路:利用服务端请求不会跨域的特性,让接口和当前站点同域。**<br />代理适用的场景是:生产环境不发生跨域,但开发环境发生跨域。<br />
**思路:利用服务端请求不会跨域的特性,让接口和当前站点同域。**
代理适用的场景是:生产环境不发生跨域,但开发环境发生跨域。
![crossDomain](/yifu-study-front-share/images/crossDomain/img3.png)
像是vue中,一般是这么处理。现在常用的vue等框架都有解决方案。
......@@ -303,12 +316,13 @@ proxyTable: {
```
<a name="qs5RQ"></a>
### 方法四:Nginx 反向代理
Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。<br />使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。<br />主要是后端进行nginx配置,就不讲了。
<a name="OoScp"></a>
Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。
使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。
主要是后端进行nginx配置,就不讲了。
### 方法五:websocket
Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。什么是全双工通信 ?简单来说,就是在建立连接之后,server 与 client 都能主动向对方发送或接收数据。<br />以第**三方库 ws** 为例:
Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。什么是全双工通信 ?简单来说,就是在建立连接之后,server 与 client 都能主动向对方发送或接收数据。
以第**三方库 ws** 为例:
```jsx
........
const WebSocket = require('ws');
......@@ -324,9 +338,9 @@ ws.on('message', function incoming(data) {
});
... ...
```
<a name="BuN2e"></a>
### 方法六:window.postMessage()
此方法可以安全地实现跨源通信。window.postMessage() 方法允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不用管是否跨域,可以用这种消息传递技术来实现安全的通信。这项技术称为“**跨文档消息传递**”,又称为“**窗口间消息传递**”或者“**跨域消息传递**”。<br />它可用于解决以下方面的问题:
此方法可以安全地实现跨源通信。window.postMessage() 方法允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不用管是否跨域,可以用这种消息传递技术来实现安全的通信。这项技术称为“**跨文档消息传递**”,又称为“**窗口间消息传递**”或者“**跨域消息传递**”。
它可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
......@@ -341,7 +355,9 @@ otherWindow.postMessage(message, targetOrigin, [transfer]);
> message:要发送的消息。它将会被结构化克隆算法序列化,所以无需自己序列化,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化。
> **targetOrigin:**“目标域“。URI(包括:协议、主机地址、端口号)。若指定为”*“,则表示可以传递给任意窗口,指定为”/“,则表示和当前窗口的同源窗口。当为URI时,如果目标窗口的协议、主机地址或端口号这三者的任意一项不匹配 targetOrigin 提供的值,那么消息就不会发送。
**接收消息**<br />如果指定的源匹配的话,那么当调用 postMessage() 方法的时候,在目标窗口的Window对象上就会触发一个 message 事件。<br />获取postMessage传来的消息:为页面添加onmessage事件。
**接收消息**
如果指定的源匹配的话,那么当调用 postMessage() 方法的时候,在目标窗口的Window对象上就会触发一个 message 事件。
获取postMessage传来的消息:为页面添加onmessage事件。
```jsx
window.addEventListener('message',function(e) {
var origin = event.origin;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment