OPTIONS预检请求preflight request

CORS机制中,发送预检请求是一种保护机制,保护资源不被未授权的请求修改

服务器基于预检请求头部信息来判断是否接受接下来的实际请求。和授权服务很像,预检请求通过,浏览器后续对同一服务的请求,不需要做跨域询问;服务端不想支持跨域访问,则啥也不用做。


预检请求头request header关键字段:

Access-Control-Request-Method

告诉服务器实际请求所使用的HTTP方法

Access-Control-Request-Headers

告诉服务器实际请求所携带的自定义首部字段,本次实际请求首部字段中content-type为自定义

预检请求头request header关键字段

预检响应头response header的关键字段:

Access-Control-Allow-Methods

返回服务端允许的请求,包含GET/HEAD/PUT/PATCH/POST/DELETE

Access-Control-Allow-Credentials

允许跨域携带cookie(跨域请求要携带cookie,必须设置为true)

Access-Control-Allow-Origin

允许跨域请求的域名,这个可以在服务端配置一些信任的域名白名单

Access-Control-Request-Headers

客户端请求所携带的自定义首部字段content-type

此次OPTIONS请求返回了响应头的内容,但没有返回响应实体response body内容

第2次请求

这是本来要发送的请求,如图所示是普通的post请求。

其中Content-Typeapplication/json是此次和后端约定的请求内容格式,这也是为什么会发送options请求的原因之一。

实际请求

OPTIONS请求

使用OPTIONS方法对服务器发起请求,可以检测服务器支持哪些 HTTP 方法。但是我们并没有主动发起OPTIONS请求,OPTIONS请求为何会自动发起?

OPTIONS请求自动发起

MDN规范要求,对那些可能对服务器数据产生副作用的HTTP请求方法特别是GET以外的HTTP请求,或者搭配某些MIME类型的POST请求),浏览器必须首先使用OPTIONS方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。

所以这个跨域请求触发了浏览器自动发起OPTIONS请求,看看此次跨域请求具体触发了哪些条件。

OPTIONS预检请求触发条件

优化OPTIONS请求:

Access-Control-Max-Age 或 避免触发

一旦达到触发条件,跨域请求便会一直发送2次请求,这样增加的请求数是否可优化?答案是可以,OPTIONS预检请求的结果可以被缓存

Access-Control-Max-Age

这个响应首部表示preflight request(预检请求)的返回结果(即Access-Control-Allow-Methods和Access-Control-Allow-Headers提供的信息)可以被缓存的最长时间,单位是秒。

如果值为-1,则表示禁用缓存,即每一次请求都需要提供OPTIONS预检请求进行检测。

避免出现预检请求,需要使得你的请求满足简单请求的两个条件。

比如在使用JWT鉴权时,可能会把你的token放在请求头的authorization字段,因为这个字段超出了简单请求的范围,所以请求会变成非简单请求。这时可以不把token放在authorization请求头中。

尽量避免触发OPTIONS请求,上面例子中把content-type改掉是可以的。在其他场景,比如跨域并且业务有自定义请求头的话就很难避免了。现在使用的axios或者superagent等第三方ajax插件,如果出现CORS预检请求,可以看看默认配置或者二次封装是否规范。


出现预检请求后,进行服务器配置,分别设置好Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers,使得你的非简单请求能够通过预检请求。

如果使用Hapijs的话,只需要在路由配置中增加cors: true配置即可。

你可能感兴趣的:(OPTIONS预检请求preflight request)