聊聊CORS的那些事儿

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。当两个地址scheme+host+port不一样的时候,就是不一样域的地址。html

1. 为何有CORS

cors是浏览器的策略,目的是为了保证网络上资源调用的安全性。若是浏览器仅仅是访问资源,不会存在跨域问题,好比访问图片,JS等文件;可是若是是读取元数据,就会受到浏览器CORS的限制,好比AJAX请求。前端

2. CORS请求类型

浏览器将CORS请求分红两类:简单请求(simple request)和非简单请求(not-so-simple request)。web

  • 请求方法是如下三种方法之一:HEAD,GET,POST
  • HTTP的头信息不超出如下几种字段:Accept,Accept-Language,Content-Language,Last-Event-ID,Content-Type: 只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

知足以上条件的为简单请求,不然为非简单请求(好比常见的自定义header字段,或是Content-Type:application/json等)。json

2.1 简单请求

对于简单请求,浏览器发送请求时会在request header里添加Origin字段,标记请求源。服务器处理请求后,返回响应信息,浏览器检查响应信息,发现响应头里没有设置Access-Control-Allow-Origin等跨域信息,会拦截请求,并抛出错误。跨域

2.2 非简单请求

非简单跨域请求在发送时,浏览器会增长一个options预检请求。大概流程以下:浏览器

  • 浏览器发送一个post请求,请求头里添加过自定义字段
  • 浏览器发现是个非简单请求,会先发一个options的预检请求(prefight request)
  • 预检请求里浏览器会检查服务器端返回的response,若是response里添加过跨域字段,则预检请求经过
  • 浏览器再发送真实的post请求

请求头设置自定义字段

当非简单请求里添加过自定义请求头字段,则 response 里须要同步设置 Access-Control-Allow-Headers: '自定义header字段名',此时预检请求才会校验经过。缓存

// Request
headers: {
  'Content-Type': 'application/json',
  'system': 'web',
  'version': 'v1.0'
}
复制代码
// Response
'Access-Control-Allow-Headers': 'Content-Type, system, version'
复制代码

跨域获取cookie

跨域读取cookie, 须要知足以下三个条件:安全

  • 客户端设置 withCredentials: true(credentials:'include'),表示赞成发送cookie
  • 服务端设置 Access-Control-Allow-Credentials: true,表示赞成接收cookie
  • Access-Control-Allow-Origin 指定固定域名

前端读取响应头header字段

通常前端只能读取resopnse body,若是想要读取自定义的response header信息,就须要设置Access-Control-Expose-Headers字段,指定须要暴露出去的header字段,这样前端就能够经过JS来读取响应头里的header信息了。服务器

// js
let system = response.headers.get('system');
复制代码
// response
Access-Control-Expose-Headers: 'system'
复制代码

支持GET、HEAD,POST以外的请求类型

若是某个请求类型是delete,则响应头里须要设置Access-Control-Allow-Methods字段。markdown

// response
Access-Control-Allow-Methods: 'delete'
复制代码

缓存预检请求

可使用 Access-Control-Max-Age 设置预检请求的有效期。在这段时间内,同个请求的预检请求只会请求一次。

// response
Access-Control-Max-Age: 100  // 100秒内使用缓存过的预检请求
复制代码

3. 跨域头设置

3.1 Access-Control-Allow-Origin

值为 * 或是固定的域名,表示容许跨域请求的域名。

3.2 Access-Control-Allow-Credentials

值为 true/false,表示服务器是否接收Cookie。想要跨域传递cookie,除了服务端Access-Control-Allow-Credentials: true接收cookie外;客户端请求也须要设置withCredentials: true,表示浏览器赞成发送cookie。另外 Access-Control-Allow-Origin 必须是个指定的域名。

3.3 Access-Control-Allow-Headers

值为请求头里设置的自定义header字段。

3.4 Access-Control-Expose-Headers

值为须要暴露出去的header字段。

3.5 Access-Control-Allow-Methods

跨来源的请求只接受三种类型GET、HEAD,POST。除此以外,若是是其它请求类型,则响应头里须要设置Access-Control-Allow-Methods: 'xxx'。

3.6 Access-Control-Max-Age

Access-Control-Max-Age 指定本次预检请求的有效期,单位是秒。

参考资料

www.ruanyifeng.com/blog/2016/0…

mp.weixin.qq.com/s/y8e1HLNzb…

相关文章
相关标签/搜索