-
cors是浏览器跨域的一种规范,规定的跨域方案:通过一系列http请求头去控制跨域行为。
-
将请求分为两类:简单请求(GET\HEAD\POST)、预检请求(可以粗略地描述成可能对服务器数据造成影响的请求)。
简单请求的满足条件
3.简单请求过程如下:
- 浏览器在请求头中带上origin字段
- 服务器返回Access-Control-Allow-Origin响应头,表明允许访问此资源的“域”的名单,并同时将正确的相应内容返回。由客户端(浏览器)去判断是否将相应内容拦截:
- 若允许客户端访问,则请求正常完成
-
若不允许客户端访问,则响应被浏览器拦截,其浏览器报错结果如图
4.预检请求(preflight)的过程如下:
-
浏览器发起一个Options(options请求介绍看下一篇)请求,带上3个字段
origin
Access-Control-Allow-Method
Access-Control-Allow-Headers
-
服务器收到请求,返回最多6个字段
-
Access-Control-Allow-Origin
允许访问此接口的“域”白名单 -
Access-Control-Allow-Method
允许的实际请求的方法 -
Access-Control-Allow-Headers
允许的实际请求的头部字段 -
Access-Control-Max-Age
过期时间,过期前只要未关闭页面,此请求都不会再预检 -
Access-Control-Expose-Headers
XHR的getResponseHeaders只能获取到6个基础性的响应头 ,若是想让其获取到更多,需在此指定白名单,说明哪些请求头可以暴露给它 -
Access-Control-Allow-Credentials
- true 允许预检完毕之后的实际请求带上认证信息,浏览器能读到response
- false 不允许预检完毕之后的实际请求带上认证信息,若浏览器“不听话”,带了认证信息,则浏览器不能读到response(如何携带认证信息参考附加部分)
-
只有前三个字段是控制预检是否通过的,即实际请求能否发起。后三个字段是控制实际请求发起之后的行为的。尤其是最后一个Allow-Credentials
,预检通过后它无论是何值实际请求都会发起,只不过如果带了认证信息(如何携带认证信息看文末),而Allow-Credentials
为 false
的话,实际请求的相应结果会被浏览器拦截,和上面简单请求的响应被拦截一样
前三个字段的条件满足之后,预检通过,随即发起实际请求
前三个字段的条件未满足,预检失败,实际请求被拦截,浏览器报错如图
5.附:如何携带认证信息?
对Fetch 与 CORS,可以使用 HTTP cookies 和 HTTP 认证信息发送身份凭证。一般而言,对于跨域
XMLHttpRequest
或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位。
如果要携带cookie的话,不能手动在请求头里设置cookie,浏览器会报错的。
手动设置cookie报错
如果是想带上cookie,需要设置
xhr.withCredentials = true;
设置好之后,如果本站有cookie存在,请求的时候就会自动带上了
参考文献:
网友评论