前言
以前不太明白 option 请求具体是干嘛的,学习过 CORS 后才豁然开朗。
CORS 的全称是“跨域资源请求” (Cross-origin resource sharing)。
两种请求
简单请求的判断条件:同时满足以下两个条件就属于简单请求。
- 请求方法是
HEAD
、GET
、POST
之一; - HTTP的头信息不超出以下范围:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:
application:x-www-form-urlencoded
、multipart/form-data
、text/plain
简单请求
简单请求不会触发 CORS 预检请求,而是直接发起 CORS 请求。
原理分析:
- 浏览器会直接在请求头中增加一个
Origin
字段,用来说明请求来自哪个域(协议 + 域名 + 端口); - 服务器根据
Origin
字段判断是否同意此次请求。(服务器可自行通过Access-Control-Allow-Origin
设置白名单) - 如果不同意此次请求,服务器返回的响应头中不包含 Access-Control-Allow-Origin,浏览器就会拦截响应,抛出异常。
- 如果同意请求,服务器返回的响应头中会多出
Access-Control-
相关的字段。
非简单请求
非简单请求要求必须首先使用 OPTIONS
方法发起一个预检请求到服务器,以获知服务器是否允许此次请求。
为什么需要预检请求(preflight)?
解答:CORS 出现之前,请求属于简单请求,当 CORS 规范推出以后,多了非简单请求,那么传统的没有 CORS 支持的服务器如何应对这些新增的请求呢?
- 不支持 CORS 的服务器没有对
Access-Control-Allow-Origin
、以及某些请求方法进行判断,此时如果没有预检请求,服务器将会直接收到跨域请求,如果请求方法是DELETE
,那么将会对数据库中的业务数据产生影响。 - 如果服务器支持 CORS ,此时没有预检请求,服务器端仍然会对请求给出响应,最后仅仅是浏览器拦截了响应,可此时为时已晚。
推荐阅读:
探索 CORS 中的预检请求
引入预检请求的动机
为什么跨域的post请求区分为简单请求和非简单请求和content-type相关?
浏览器预检请求(preflight request)
字段介绍
请求首部字段
-
Origin
表明预检请求或实际请求的源站,这是浏览自己加的,不需要用户关心。 -
Access-Control-Request-Method
用于预检请求,将实际请求用到的 HTTP 请求方法告诉服务器。 -
Access-Control-Request-Headers
用于预检请求,将实际请求所携带的首部字段告诉服务器。
响应首部字段
-
Access-Control-Allow-Origin
指定运行访问的该资源的白名单。 -
Access-Control-Allow-Credentials
- 简单请求:是否允许浏览器读取响应内容
- 预检请求:实际请求中是否可以使用凭证(credentials)
-
Access-Control-Allow-Methods
用于预检请求,实际请求所允许使用的请求方法。比如后端可能没有运行使用OPTIONS
请求方法,此时预检请求就会失败。 -
Access-Control-Allow-Headers
用于预检请求,实际请求所允许携带的请求头。比如自定义Authorization
字段用于携带 token 。 -
Access-Control-Max-Age
预检请求的结果能被缓存多久。在缓存时间内,浏览器不会对同一请求再次发起预检请求。
网友评论