写点什么

CORS 跨域

作者:六月的
  • 2022-10-19
    上海
  • 本文字数:1376 字

    阅读完需:约 1 分钟

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;}
复制代码


用户头像

六月的

关注

还未添加个人签名 2019-07-23 加入

还未添加个人简介

评论

发布
暂无评论
CORS跨域_CORS_六月的_InfoQ写作社区