为什么会这样
同源策略
先说一下这个同源策略。
他为什么出现,为了安全。
通过限制不同源之间的交互,避免一些浏览器网络层面的攻击:
- XSS
- CSFR
什么叫不同源
知道什么叫同源就知道什么是不同源了。
协议、域名、端口一样就是同源。后面的请求路径、请求参数、锚点什么的不重要。讲一下怎么防住这些攻击的
XSS就是往页面中插入恶意的 html 代码 —— 利用用户对网站的信用,用户以为自己做的是自己想做的
CSFR 就是跨站请求伪造,骗有权限的浏览器去做操作,因为用户给过他权限,浏览器就以为是用户自己想做的
不设置同源策略,就会导致只能保证请求来自用户的浏览器,但是不能保证这是用户自己真正想做的
而非同源的可以限制网站行为,不给你看 cookie、localStorage、indexDB、请求等,就不能通过用户历史访问留下的权限进行恶意操作
为什么要跨域
现在项目基本前后端分离,就会处在不同的域名上。当前端直接请求后端的接口,就会报错。很安全,但是很不方便 ==
就自己本地启两服务器端口号都会不一样好吧
那要怎么跨过去
JSONP
AJAX
/XMLHttpRequest
/Fetch
API的方式来发起请求是会收到跨域拦截的,但是 html 中调用 JS 是没事的—— 也就是说,拥有 src 属性的 标签就能跨域。
JSONP 就是这样,通过发送带有会回调函数 的 GET 请求,让服务器端将接口返回数据作为参数放到回调函数里。客户端就能拿到 回调函数的数据。
有点像 react 中子组件向父组件传递信息的方式有没有
但是这个方法限制极大
- 只有 get 方法,因为标签请求外部资源也就只是 get 方法
- 把操作数据的方法放到标签里面,本来就很不方便
代理跨域
在前后端加一层代理,让跨域请求没“跨域”webpack 设置代理
在 webpack 中可以设置 proxy 来得到接口代理的能力,代理服务器会将前端发送的请求映射为 同域请求
类似原理的还有:module.exports = {
//...
devServer: {
//...
proxy: {
//...
}
},
//...
};
- Nginx 方向代理
- Node 中间件代理
CORS 跨域
Cross-Origin Resource Sharing 跨域资源共享,这是浏览器自身提供的功能
作用就是允许服务器规定哪些 域 是可以跨域过去的现代浏览器基本都支持,一般推荐用这个
虽然说这是浏览器提供的功能,但是具体实现控制和通信是在服务器端。由服务器端来控制哪些域可以跨域
简单请求
怎么算简单请求:
方法简单
比如这几种
- get
- post
-
头部简单
头部拥有的属性仅在这下面几个范围内
Accept
- Accept-Language
- Content-Language
- Content-Type
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
比如你自己自定义一个头部字段的请求就不属于简单请求的
XMLHttpRequestUpload 简单
XMLHttpRequest.upload 属性返回一个 XMLHttpRequestUpload对象,用来表示上传的进度。这个对象是不透明的,但是作为一个XMLHttpRequestEventTarget,可以通过对其绑定事件来追踪它的进度。
- XMLHttpRequestUpload 对象上没有注册事件监听
- XMLHttpRequestUpload 可以用 XMLHttpRequest.upload 属性访问
ReadableStream 简单
流操作 API 中的ReadableStream 接口呈现了一个可读取的二进制流操作。Fetch API 通过 Response 的属性 body(en-US) 提供了一个具体的 ReadableStream 对象。
这个直接不能有
操作
浏览器发出 CORS 请求时,要在头部添加 Origin
字段来告诉服务端请求域
当服务端收到 Origin ,就会判断是否接受跨域请求:
- 接受就在返回的响应中添加 CORS 相关的信息
Access-Control-Allow-Origin
字段(必填),表示能够给接受的域名,*
表示全部域名
- 不添加相关字段的话就是不同意
- 返回正常的 Http 响应,但是浏览器就会发现不对劲,就会抛出跨域错误
非简单请求
非简单请求,就是不是简单请求的请求
除了简不简单的区别,还有他在发送正式请求之前,会先发出一个预检请求。必须得到服务端同意请求才能发送正式请求~
预检查请求
用的请求方法是 Option ,必须标明 Origin,并且带上两个特殊字段:
Access-Control-Request-Method
:告诉服务器端正式请求想要用到的请求方法Access-Control-Request-Headers
:告诉服务器端正式请求想要用到的额外头部字段
服务器端收到请求后,也会返回这两个字段来告诉他能接受的请求方法和额外头部字段。
而正式请求就和简单请求差不多了,前面两个字段的作用也就差不多是扩充简单请求的约束范围:
- 方法简单
- 头部简单
然后就是一样的,同意跨域就加上Access-Control-Allow-Origin
…不重复赘述了
CORS 小结
CORS 跨域算是比较常用、好用、重要的方法,主要实现在于服务器端,需要在服务器端设置允许跨域的