CORS小结


1、说明

该文基于故事图文并茂地讲述了跨域的前生今世,因为文章是故事形式,里面的一些要点都只是一提而过,下面再次总结一下,顺序就和该文讲述的顺序一致

本文参考文章有:

https://blog.csdn.net/xiaoxinshuaiga/article/details/80766369

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

2、浏览器的基本原理

浏览器的职责划分包括:

  1. 负责网络连接部分;
  2. 负责存储管理部分,管理 Cookie、LocalStorage 、SessionStorage 等;
  3. 网页渲染部分;
  4. JS引擎;

网页渲染负责把来自网络的HTML文件进行解析,构建DOM树,再拿CSS文件,构建CSSOM树,最后把网页划出来

网页在渲染的时候,遇到

上例中,服务端的 test.js 脚本能够请求到,




    
    
    


后端的 test.js 内容如下:

testFunction({
    "data": 1234,
    "message": "OK"
});

示例中,testFunction() 函数定义好之后,接下来的标签请求后端的js脚本,得到之后,执行testFunction() 方法,数据也顺利传递进来了

然后,逐渐演化,后端的脚本也不用写死,因为src是GET方法,可以将回调函数直接传给后端,让后端解析




    
    
    


逐渐地,各大主流框架都有了 JSONP 的封装,这里不再一一列举,但是需要注意的事是,JSONP 虽然看起来和 Ajax 相似,但是本质上和 Ajax 是两种不同的方式

5、CORS

有了 JSONP,跨域的问题暂时解决了,但是 JSONP 怎么看都是一种取巧的技术,使用起来会有很多的限制,比如只能使用 GET 方法,调用失败也不会返回错误等

后来,浏览器厂商推出了 CORS(Cross-origin resource sharing) 技术,CORS 是一种浏览器机制,它使用 HTTP 的协议头来允许不同服务器的请求

CORS 的大致方式是,在正式的请求之前,先发一个 OPTION 请求,询问服务器是允许接下来的跨域请求。约定,在 OPTION 请求中新增几个字段

  • Origin: 发起请求原来的域;

  • Access-Control-Request-Method: 将要发起的跨域请求方式(GET/POST等);

  • Access-Control-Request-Headers: 将要发起的跨域请求中包含的请求头字段

服务器在 OPTION 请求的 response 中表明是否允许此跨域

  • Access-Control-Allow-Origin: 允许的域(*表示所有域)
  • Access-Control-Allow-Method: 允许哪些请求方式(GET/POST等)
  • Access-Control-Allow-Headers: 允许哪些请求头字段
  • Access-Control-Allow-Credentials: 是否允许携带Cookie

如下图所示

浏览器接受到服务器的 response 后,检查,如果不符合要求,就拒绝接下来的请求

然而,每次请求都先发起一次 OPTION 预请求费时费力费资源,因此,又约定,有两种方式,可以避免预检请求:

一是 简单请求,即不会触发 CORS预检请求的请求。符合下面所有条件的请求,即为简单请求:

  1. 使用的方式为 GET/POST/HEAD 其中之一;
  2. HTTP 请求头中不超过以下五种字段:
    1. Accept
    2. Accept-Language
    3. Content-Language
    4. Last-Event-ID
    5. Content-Type
  3. Content-Type 的值仅限于以下三者之一:
    1. text/plain
    2. multipart/form-data
    3. application/x-www-form-urlencoded

二是,在前一次请求之后,服务器的 response 中会带有一个 Access-Control-Max-Age ,表明这个询问的有效期,浏览器的请求在有效期内的,也可不进行预检请求

6、CORS和JSONP的比较

CORS 和 JSONP 的方式不同,但是目的相同,CORS 的功能比 JSONP强大太多

JSONP 因为使用 src 值来请求,所以只支持 GET 方法,而 CORS 支持所有类型的 HTTP请求

但是,JSONP 可以支持老式的浏览器,还可以向不支持 CORS 的服务器请求数据