CORS 跨域资源共享 (cross-originresource sharing)
是一个W3C标准,允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,
1.SOP(Same Origin Policy)同源策略
浏览器同源策略是,浏览器安全的基石,由Netscape公司引入浏览器。基本内容是指,如果非同源,以下的一些操作无法完成
- Cookie,LocalStorage,IndexDB,无法读取
- DOM无法获取
- AJAX请求不能发送 同源主要指三个方面
- 协议相同:
httphttps - 域名相同:
- 端口相同:
同源政策的目的是为了保障用户信息安全,防止恶意的网站窃取数据,但是在一些情况下,也不是那么方便。目前而言,可以从服务端和客户端(浏览器)来解决。
2.跨文档通讯API(Cross-document messaging)
H5规范内,引入一种新的跨源信息读取方式,可以跨源获取当前不同网页上的数据,主要方式为
Window.PostMessage(message,location),接受端,可以通过监听Message事件来进行数据的获取,
3.AJAX内处理解决同源策略
AJAX请求只能发送给同源的网站,否则会报错,除了服务器架设代理外
- JSONP
- WebSocket
- CORS
3.1 JSONP 服务器和客户端之间的跨源通讯
在网页内,添加一个<script>标签,通过这个script标签,向服务器发起请求,服务器在接收到请求后,将数据放在一个指定名字的回调函数里传回来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//添加<script>标签
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
//相应的返回函数,
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
<script>元素请求的脚本,直接作为代码进行运行,作为参数的数据被视为JavaScript对象,而不是字符串。避免了被同源策略限制。
3.2 WebSocket
WebSocket是一种通讯协议(本质上也是应用层的一种协议,和 HTTP 同级别,但是目前使用,一般是在HTTP 基础上来使用 WebSocket协议),使用ws://和wss://作为协议前缀,不实行同源策略
3.3 CORS 跨域资源共享
CORS是一个标准,运行浏览器向跨源服务器发出 XMLHttpRequest请求。
CORS通讯过程,由浏览器自动完成,不需要用户进行相关的处理。浏览器发现了跨源请求,就会自动添加附加头部信息。CORS的关键是服务器,只要服务器实现了CORS接口就可以实现跨源通讯。
CORS请求分为 简单请求 和 非简单请求。
简单请求:
- 请求方法为:
HEADGETPOST - 请求头信息不超出:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded、multipart/form-data、text/plain
简单请求,浏览器发出CORS请求,只需要在头部添加一个origin字段。用来说明请求来自的协议、域名、端口。
1
2
3
4
5
6
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
如果origin字段内的源,没有在允许范围内,服务器就会返回一个正确回应,但是没有Access-Control-Allow-Origin字段,从而抛出错误。而如果在允许返回内,服务器会多几个头信息字段
1
2
3
4
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin:必须字段,为*或者origin的值Access-Control-Allow-Credentials:可选,是否允许发送Cookies,默认Cookies不包括在CORS请求内,如果要发送Cookies,就不能将上一个字段设置为*
(3)Access-Control-Expose-Headers
该字段可选。CORS请求时,
XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值。
复杂请求:针对服务器有特殊要求,请求方法为PUT DELETE,或者请求的Content-Type为application/json
复杂请求在正式通信前,会增加一次HTTP查询请求(请求方式为OPTIONS),称为预检,浏览器先询问服务器是否可以发送。
1
2
3
4
5
6
7
8
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
同源策略虽然很厉害,但是浏览器中仍然存在一些不受制于其影响的 api、标签,例如常见的Img,iframe 和 Script 标签,即不受到同源信息策略的限制。
在实际书写 img 标签时,可能在对应 src 上,编写对应的 json 请求 url,那么就可能产生,服务器跨域返回数据。
CORB (Cross-Origin Read Blocking)跨源读取阻碍
在加载可以进行跨源的资源是,在资源载入页面之前,对其进行识别和拦截的算法。对浏览器的渲染进行进行保护
an algorithm by which dubious cross-origin resource loads may be identified and blocked by web browsers before they reach the web page.
浏览器在加载可以跨域资源时,在资源载入页面之前,对其进行识别和拦截的算法。
哪些内容受CORB保护
当前有三种内容类型受保护,分别是json、html 和 xml。关于如何针对每种内容类型 CORB 如何对其进行保护,文档中有详细的章节进行介绍,规则均是对内容格式进行一些有针对性的校验,以确认它确实是某个内容类型。这个校验结果最终影响 CORB 的运作方式。
CORB如何起作用
CORB会对响应内容为上诉三种数据的response进行保护,具体如下:
CORB 会根据如下步骤来确定是否对 response 进行保护(如果响应的内容格式是 json、html 或者 xml):
- 如果 response 包含
X-Content-Type-Options: nosniff响应头部,那么如果 Content-Type 是以下几种的话, response 将受 CORB 保护:html mime type- xml mime type(除了 image/svg+xml)
- json mime type
- text/plain
- 如果 response 的状态是 206,那么如果 Content-Type 是以下几种的话, response 将受 CORB 保护:
- html mime type
- xml mime type(除了 image/svg+xml)
- json mime type
- 否则,CORB 将尝试探测 response 的 body:
- html mime type,并且探测结果是 html 内容格式,response 受 CORB 保护
- xml mime type(除了 image/svg+xml), 并且探测结果是 xml 内容格式,response 受 CORB 保护
- json mime type,并且探测结果是 json 内容格式,response 受 CORB 保护
- text/plain,并且探测结果是 json、html 或者 xml 内容格式,response 受 CORB 保护
- 任何以 JSON security prefix 开头的 response(除了 text/css)受 CORB 保护
这里值得一提的是,对于探测是必须的,以防拦截了那些依赖被错误标记的跨源响应的页面(比如,图片资源但是格式却被标记为 text/html)。如果不进行格式探测,那么会有16倍以上的 response 被拦截。
CORB 如何拦截一个响应
当一个 response 被 CORB 保护时,它的 body 会被覆盖为空,同时 headers 也会被移除(当前 Chrome 仍然会保留 Access-Control-* 相关的 headers)。
关于 CORB 的工作方式,一定要和 CORS 做区分,因为它要防止这些被拦截的数据进入渲染当前页面进程的内存中,所以它一定不会被加载并读取。这不同于 CORS,因为后者会做一些过滤操作,数据虽然不可被加载,但是可能仍然保留在渲染进程的内存中。
参考文章: 30 分钟理解 CORB 是什么 - SegmentFault 思否 跨域资源共享 CORS 详解 - 阮一峰的网络日志 (ruanyifeng.com)