定义
- CORS全称是跨域资源共享(Cross-orgin resource sharing)
作用
- 允许浏览器向跨源服务器发起请求,突破了同源限制问题
使用
- 浏览器和服务器要同时支持,IE版本不能低于10
- 分为简单请求和非简单请求,以下分别从几个方面来区分,下面SR为简单请求缩写,NSR为非简单请求
1、请求方法
SR—POST/GET/HEAD
NSR—PUT/DELETE
2、Content-Type值
SR—application/x-www-form-urlencoded、multipart/form-data、text-plain
NSR—application/json
3、基本流程
SR—one step
浏览器直接发出CORS请求,并在头部携带一个origin字段,服务器根据这个值决定是否同意请求
GET /cors HTTP/1.1
Origin: http://api.eurus.com //说明请求来自哪个源,包括协议、域名、端口
Host: api.eurus.com
NSR—one step
浏览器先发送一个OPPTIONS的预请求,询问服务器当前网页所在的域名是否在许可名单内,以及可以使用的HTTP动词和头信息,确认可以之后才会发送CORS请求,比SR多了两个字段,下面是预检请求的头信息
OPTIONS /cors HTTP/1.1
Origin: http://api.eurus.com //同上
Access-Control-Request-Method: PUT //必须字段,CORS请求用到的请求方法
Access-Control-Request-Headers: X-Custom-Header //额外的头信息字段
Host: api.eurus.com
SR—second step
服务器收到请求,检查origin字段,如果在允许范围内,那么会返回如下信息
Access-Control-Allow-Origin: http://api.eurus.com //表示值是origin字段的值或者是*(任意域名请求都接受)
Access-Control-Allow-Credentials: true //表示是否允许浏览器发送cookie
Access-Control-Expose-Headers: My-Header1 //表示可以获取的自定义头信息字段
如果不在允许范围控制台会输出错误信息
XMLHttpRequest cannot load http://api.alice.com.
Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
NSR—second step
服务器收到预请求会检查Origin、Access-Control-Request-Method、Access-Control-Request-Headers三个字段,确认允许之后预请求回应
Access-Control-Allow-Origin: http://api.eurus.com //同上
Access-Control-Allow-Methods: GET, POST, PUT //服务器支持的所有跨域请求方法
Access-Control-Allow-Headers: X-Custom-Header //允许的自定义头信息
如果不允许控制台会输出和SR相同的错误信息
服务器返回
Access-Control-Allow-Methods: GET, POST, PUT //同上
Access-Control-Allow-Headers: X-Custom-Header //同上
Access-Control-Allow-Credentials: true //同上
Access-Control-Max-Age: 125000 //预检请求的有效期,单位为秒,表明在此期间不需要再发送新的预请求
其他
Access-Control-Allow-Credentials值只能为true,如果不允许浏览器发送cookie删除字段即可,另外在AJAX请求中也必须打开withCredentials,缺一不可,并且Access-Control-Allow-Origin不可为*,cookie仍然遵循同源策略
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
Access-Control-Expose-Headers头信息中,getResponseHeader()只能拿到6个字段,分别是Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,想要其他字段就在这里指定,通过getResponseHeader('My-Header1')可以获取My-Header1字段值