note icon indicating copy to clipboard operation
note copied to clipboard

为什么会有OPTIONS预请求 - CORS跨域

Open liuyib opened this issue 7 years ago • 0 comments

1、问题原因 进行 CORS 跨域时,在有的浏览器中有时会出现:一次动作,两次请求。 这个问题是在进行前后端分离开发时,由于跨域引起的

在以前,跨域可以使用 代理、JSONP 等方式,在现代浏览器中,我们有更好的选择:CORS。 使用 CORS 跨域,只需要在服务端设置 Access-Control-Allow-Origin 响应头,即可像访问同源接口一样访问跨域接口。

在使用 CORS 跨域时,后台采用 token 检验机制,前台发送请求必须将 token 放到 Request Headers 中,那么就需要传输自定义 Headers 信息,这时候在发送 ajax 请求时,有时一次动作会触发两次请求。一次是 OPTIONS 请求,一次是真正的请求

下面是这个问题的答案:

对于 CORS 跨域,有两种请求类型

  • 简单跨域请求
  • 复杂跨域请求(带有 OPTIONS 请求)

2、简单跨域请求 简单跨域请求满足下面两个条件。

  1. 请求方法是下面三种方法之一
  • GET
  • POST
  • HEAD
  1. 请求头信息不超过以下几种字段
  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type (只限于三个值:application/x-www-form-urlencodedmultipart/form-datatext/plain

简单跨域请求的部分响应头如下:

  • Access-Control-Allow-Origin(必选):不写会请求失败。该项控制数据可见范围,如果想对任何人可见,将其设为 *

  • Access-Control-Allow-Credentials(可选):该项控制请求是否包含 cookies 信息。包含设置为 true(必须小写),不包含,请略去该项,而不是填写 false!这一项于 XmlHttpRequest2 对象中的 withCredentials 属性应该保持一致,即 withCredentials 属性设置为 true,则该项也设置为 true;withCredentials 设置为 false,该项要略去不写,不能是 false,如果是 false 会导致请求失败。

  • Access-Control-Expose-Headers(可选):该项确定 XmlHttpRequest2 对象中 getResponseHeader 方法所能获得的额外信息。通常情况下,getResponseHeader 方法能获得如下信息:

    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma

当你需要使用 getResponseHeader 方法获取额外信息时,就需要在这一项中填写并以逗号分隔。

3、复杂的跨域请求 只要不满足上面简单跨域请求条件的请求都是复杂跨域请求。 复杂跨域请求会发送一个预请求(OPTIONS 请求)。只有预请求返回成功时,实际请求才开始执行。

预请求以 OPTIONS 的形式发送,包含域,并且包含两项 CORS 特有的内容:

  • Access-Control-Request-Method 请求方法。可以是 GET、POST、PUT、DELETE
  • Access-Control-Request-Headers 请求头。一个逗号分隔的列表

所以预请求就是提前发送一个 “权限请求”,为后面的实际请求做准备。一旦预请求返回成功,则证明权限满足。

4、解决预请求的办法 后台设置 Access-Control-Max-Age 来控制浏览器在多长时间内(单位 s)不需要发送 OPTIONS 预请求,从而减少不必要的请求。


原文链接: https://juejin.im/post/5c46af87e51d4552232feaeb

liuyib avatar Jan 22 '19 14:01 liuyib