01、索引

https://waterflow.link/articles/1665656761584

1、为什么跨域

跨域资源共享 (CORS) 是一种基于 HTTP 标头的机制,它容许服务器批示除其本身之外的任何起源(域、计划或端口),浏览器应容许从中加载资源。 CORS 还依赖于一种机制,浏览器通过该机制向托管跨域资源的服务器收回“预检”申请,以查看服务器是否容许理论申请。 在该预检中,浏览器发送批示 HTTP 办法的标头和将在理论申请中应用的标头。

跨域申请的示例:从 https://a.com 提供的前端 JavaScript 代码应用 ajax 向 https://b.com/data.json 发出请求。

出于平安起因,浏览器限度从脚本发动的跨域 HTTP 申请。 例如,ajax 和 申请的 API 遵循同源策略。 这意味着应用这些 API 的 Web 应用程序只能从加载应用程序的同一起源申请资源,除非来自其余起源的响应蕴含正确的 CORS 标头。

2、跨域的规定

CORS规范通过增加新的 HTTP 头来工作,服务器能够返回容许哪些起源从 Web 浏览器读取该信息。此外,对于可能对服务器数据造成副作用的 HTTP 办法(特地是 GET 以外的 HTTP办法 ,或具备某些 MIME 类型的 POST),标准要求浏览器“预检”申请(先发送OPTIONS申请),而后在服务器“容许”后发送理论申请。

CORS 失败会导致谬误,但出于平安起因,JavaScript 无奈取得无关谬误的详细信息。所有代码都晓得产生了谬误。确定具体出了什么问题的惟一办法是查看浏览器的控制台以获取详细信息。

3、跨域场景

1、不会触发预检

简略的申请不会触发预检,那什么是简略的申请呢?

  • 首先申请办法必须是GET、HEAD、POST其中之一
  • 除了客户端主动设置的header头(比方:Connection、User-Agent等),只能设置如下的这些header头

    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type:只容许application/x-www-form-urlencoded、multipart/form-data、text/plain类型
    • Range:只能是一些简略的header头,比方bytes=256-或者bytes=127-255

上面是一个简略申请的流程:

  1. 首先客户端会向a.com会向服务端b.com发送申请,并带上源域名。
  2. 作为响应,服务器返回一个带有 Access-Control-Allow-Origin: * 的 Access-Control-Allow-Origin 标头,这意味着该资源能够被任何起源拜访。(个别容许某个域或者某几个域,能够用正则)

2、会触发预检

和简略申请不同,处于平安思考,会先向“预检”申请,浏览器首先应用 OPTIONS 办法向另一个源上的资源发送 HTTP 申请,以确定理论申请是否能够平安发送。

上面是预检申请的流程:

  1. 首先客户端header头曾经不合乎简略申请的header,这时会触发预检。
  2. 客户端发送OPTIONS申请,以获取容许跨域的header头,会返回204 No Content的状态码
  3. 预检胜利之后,客户端会发送失常的POST申请

3、nginx跨域配置

留神:如果nginx设置跨域反复,客户端console也会提醒反复跨域

add_header Access-Control-Allow-Origin * always; # 容许所有add_header Access-Control-Allow-Methods 'PUT,POST,GET,DELETE,OPTIONS'; #容许指定的申请办法add_header Access-Control-Allow-Headers 'token,eceibstoken,powercode,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; # 容许指定的header头add_header Access-Control-Expose-Headers *; # 指定客户端能够拜访哪些header# 如果是预检申请,返回204if ($request_method = OPTIONS) {    return 204;}