一、什么是options请求

在正式发起跨域http请求之前,浏览器会根据需要发起一次预检(option请求),用来让服务端返回请求允许的方法(如get、post),orgin(来源|域名),以及是否需要Credentials(认证信息)等。

二、什么情况下

浏览器将CORS请求分为两类:简单请求(simple request)和非简单请求(not-simple-request),简单请求浏览器不会预检,而非简单请求会预检。这两种方式怎么区分?

同时满足下列三大条件,就属于简单请求,否则属于非简单请求

  • 请求方式只能是:GET、POST、HEAD
  • HTTP请求头限制这几种字段:Accept、Accept-Language、Content-Language、Content-Type、Last-Event-ID
  • Content-type只能取:application/x-www-form-urlencoded、multipart/form-data、text/plain

三、简单请求 非简单请求

简单请求

对于简单请求,浏览器直接请求,会在请求头信息中,增加一个origin字段,来说明本次请求来自哪个源(协议+域名+端口)。服务器根据这个值,来决定是否同意该请求。服务器返回的响应会多几个和跨域相关的头信息字段

  • Access-Control-Allow-Origin:该字段是必须的,* 表示接受任意域名的请求,还可以指定域名
  • Access-Control-Allow-Credentials:该字段可选,是个布尔值,表示是否可以携带cookie,(注意:如果Access-Control-Allow-Origin字段设置*,此字段设为true无效)
  • Access-Control-Allow-Headers:表明服务器允许请求中携带字段 ,如Cache-Control、Content-Type、Expires等
  • Access-Control-Max-Age:有效时间,在有效时间内,浏览器无须为同一请求再次发起预检请求

非简单请求

非简单请求是对那种对服务器有特殊要求的请求,比如请求方式是PUT或者DELETE,或者Content-Type字段类型是application/json。都会在正式通信之前,增加一次HTTP请求,称之为预检。

浏览器会先询问服务器,当前网页所在域名是否在服务器的许可名单之中,服务器允许之后,浏览器会发出正式的XMLHttpRequest请求,否则会报错。(备注:之前碰到预检请求后端没有通过,就不会发正式请求)

就Content-Type为application/json为例:对比两张图片,一次预检请求,一 次正式请求:

express 被跨域请求 跨域请求 options_Access

express 被跨域请求 跨域请求 options_字段_02


很明显,请求头中预检请求不会携带cookie,正式请求会携带cookie和参数。一旦服务器通过了“预检”请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样

【注意】

若后端设置了拦截器拦截请求,并对不携带cookie或者token的请求不放行。此时应该考虑到放行options请求,因为该请求header中不会携带cookie或者token