HTTP access control (CORS) 跨域问题是工作中,开发环境下,常遇到的一个问题

  • 名词解释

预检请求

Preflighted requests(options)
触发条件:

  • It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, ortext/plain, e.g. if the POST request sends an XML payload to the server using application/xmlor text/xml, then the request is preflighted.

  • It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

浏览器在发起跨域请求的时候会带着一个Origin header,那么其实就是个custom headers,那么也就会先触发一个Preflighted requests, Fetch Standard 也有提到。

指路:Fetch Standard(https://fetch.spec.whatwg.org/#cors-preflight-request)
3.2.2. HTTP requests
A CORS request is an HTTP request that includes an Origin header. It cannot be reliably identified as participating in the CORS protocol as the Origin header is also included for all requests whose method is neither GET nor HEAD.

A CORS-preflight request is a CORS request that checks to see if the CORS protocol is understood. It uses OPTIONS as method and includes these headers:

✔MDNAccess-Control-Request-Method
Indicates which method a future CORS request to the same resource might use.

✔MDNAccess-Control-Request-Headers
Indicates which headers a future CORS request to the same resource might use.

  • 为什么要发预检请求?
    我们都知道浏览器的同源策略,就是出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求,像XMLHttpRequest和Fetch都遵循同源策略。
浏览器限制跨域请求一般有两种方式:
    1. 浏览器限制发起跨域请求
    2. 跨域请求可以正常发起,但是返回的结果被浏览器拦截了
      一般浏览器都是第二种方式限制跨域请求,那就是说请求已到达服务器,并有可能对数据库里的数据进行了操作,但是返回的结果被浏览器拦截了,那么我们就获取不到返回结果,这是一次失败的请求,但是可能对数据库里的数据产生了影响。
      为了防止这种情况的发生,规范要求,对这种可能对服务器数据产生副作用的HTTP请求方法,浏览器必须先使用OPTIONS方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求。