CORS 跨域资源共享

CORS 跨域资源共享

Owner 脱浩虎
Last edited time @September 18, 2023 5:37 PM
  • 思考几个问题

    1. 跨站一定跨域吗?
    1. 为什么有些POST请求会发出去两次请求?
    1. CORS的作用是啥?
  • 同源策略

    一句话总结:

    同源策略(Same origin policy)是浏览器的一个重要安全策略, 用于保护用户的信息安全,防止恶意脚本的攻击

    "同源"指的是"三个相同":

    协议相同

    域名相同

    端口相同

    源(origin)= 协议(scheme)+ 主机名(hostname)+ 端口号(port)

    举例: www.eeo.cn

    同源策略的目的:

    是为了保证用户信息的安全,防止恶意的网站窃取数据

    举例:本地开一个服务器去访问dynamic域名接口

    如果非同源,共有三种行为受到限制:

    1. 无法读取非同源网页的 Cookie、IndexDB等

      携带cookie如果满足的条件:

      ini 复制代码
      1. 同源时:
            cookie会自动读取与存储、发送
      
      2. 同站时:
            1. 都是 http 或者 https,或者不同的情况下 Secure 属性为 false
                (即 secure 是 true 的情况下,只有 https 请求才能携带这个 cookie)
            
            2. path路径一致
                要发送请求的路径,跟浏览器端 Cookie 的 path 属性必须一致,或者是浏览器端 Cookie 的 path 的子目录,
                比如浏览器端 Cookie 的 path 为 /test,那么请求的路径必须为/test 或者/test/xxxx 等子目录才可以
      
      3. 跨站时:
          后端添加CORS响应头保证跨域请求正常,配合前端XHR.withCredentials=true即可正常发送cookie
      
          必要时添加SameSite=none;Secure或者nginx反向代理解决cookie跨站问题
          document.cookie = 'aa=bb; path=/; domain=.eeo.im; SameSite=None; Secure'
      
          后端设置:
            1. 网站开启 https 并将 Cookie 的 Secure 属性设置为 true
            2. Access-Control-Allow-Origin 设置为具体的 origin,而不是 *
            3. Access-Control-Allow-Credentials 设置为 true
            4. SameSite 属性设置为 None 
      
          sameSite属性
                Strict: 阻止发送第三方cookie
                Lax: 阻止GET以外的请求自动带上Cookie
                None: 发送第三方cookie,前提是Secure=true

    IndexDB:

    复制代码
    非关系型数据库
    持久化存储
    异步操作
    支持事务
    同源限制
    存储容量大
    1. 无法接触非同源网页的 DOM元素、属性或方法, 这是为了防止恶意网站从其他网站窃取敏感信息
    1. 无法向非同源地址发送 AJAX 请求,浏览器会阻止从一个源发出的请求获取来自其他源的响应(阻止跨域请求)
  • 什么是跨域和跨站

    子域名与当前域名是否属于跨域?

    子域名与当前域名是否属于跨站?

Cross-Origin:

makefile 复制代码
*结论: 只要 协议、域名、端口号中的任何一个不相同,就是跨域*

跨域的几个例子

bash 复制代码
协议不同: [https://www.eeo.c](https://www.eeo.com/)n 与 [http://www.eeo.c](http://www.eeo.com/)n

域名不同: [https://www.eeo.c](https://www.eeo.com/)n 与 [https://www.eeo.im](https://www.eeo.im/)

端口号不同: [https://www.eeo.c](https://www.eeo.com/)n 与 [https://www.eeo.cn:3000](https://www.eeo.com:3000/)

跨域解决方案:

javascript 复制代码
1.前端的JSONP 
2.代理服务器 
3.postMessage
4.服务端在响应头中配置CORS
5.nginx反向代理

Cross-Site

markdown 复制代码
0.*结论:*

只要 *一级域名* 不同就是跨站

eTLD+1不同就是跨站

[www.taobao.com](http://www.taobao.com/) 和 [www.baidu.com](http://www.baidu.com/) 是跨站, [www.a.taobao.com](http://www.a.taobao.com/) 和 [www.b.taobao.com](http://www.b.taobao.com/) 是同站

[a.github.io](http://a.github.io) 和 [b.github.io](http://b.github.io) 是跨站

<https://juejin.cn/post/6844904095711494151>

TLD(Top Level Domain):

less 复制代码
表示顶级域名,例如 .com、.org、.cn、[com.cn](http://com.cn/) 、github.io 等等

eTLD 表示有效顶级域名,注册于 Mozilla 维护的公共后缀列表(Public Suffix List)中,例如,.com、.co.uk、.github.io 等。

eTLD+1 则表示,有效顶级域名+一级域名,例如 [taobao.com](http://taobao.com/) 等

[公共后缀列表](https://publicsuffix.org/list/public_suffix_list.dat)

什么是一级域名?

复制代码
TLD+1

例如:

使用场景:

ini 复制代码
cookie的sameSite属性:

res.setHeader('Set-Cookie', 'name=value; SameSite=Lax;');

跨域与跨站的关系:

跨站一定跨域:

跨站说明一级域名不同,那么域名也就不同,所以跨域

跨域不一定跨站:

[www.a.taobao.com](http://www.a.taobao.com/) 和 [www.b.taobao.com](http://www.b.taobao.com/) 跨域但是同站(一级域名taobao.com相同)

preflight请求

markdown 复制代码
*什么是预检请求?*

预检请求(Preflight Request)是 CORS 中的一个可选步骤, 用于验证跨域请求是否安全。

大白话总结: 非简单请求中,客户端提前打听一下服务端支持的请求选项

*预检请求的主要特征是:*

1. 请求方法是 OPTIONS 方法

2. 浏览器请求头包含 Origin、Access-Control-Request-Method 等信息

3. 服务器需要返回 Access-Control-Allow-Origin 等头信息

4. 预检请求一般不返回内容(只需要response headers)

预检请求完成后,浏览器评估服务器返回的头信息,来判断跨域 AJAX 请求是否可以发送。

*预检请求的作用:*

用于获取服务端所支持的通信选项。

简单来说,就是可以用 options 请求去嗅探某个请求在对应的服务器中都支持哪种请求方法。

*预检请求的流程:*

1.  浏览器发现跨域 AJAX 请求为复杂请求,需要进行预检。


2.  浏览器发送 OPTIONS 请求到服务器,请求头中包含:

    -   Origin:请求页面源信息
    -   Access-Control-Request-Method:实际请求将使用的 HTTP 方法
    -   Access-Control-Request-Headers:实际请求将包含的头信息
3.  服务器接收到预检请求,验证 Origin 并检查 HTTP 方法和头信息。
4.  服务器返回响应,响应头中包含:
    -   Access-Control-Allow-Origin:允许的请求源
    -   Access-Control-Allow-Methods:允许的 HTTP 方法
    -   Access-Control-Allow-Headers:允许的请求头
5.  浏览器接收到预检响应,然后发送实际的 AJAX 请求。
6.  服务器完成实际 AJAX 请求的处理,返回对应响应。
7.  浏览器接收到响应,完成页面渲染。

预检请求的类型:

ruby 复制代码
简单请求

```
1. Method限制: 
  请求的方法是 GET、POST 及 HEAD(获取资源的元信息)

  如果请求使用了其他 HTTP 方法,就不再被视为简单请求

2. Header限制: 
  请求的 HTTP 标头只能是以下几种常见的标头:
    Accept
    Accept-Language
    Content-Language
    Content-Type
    Last-Event-ID

  HTML 头部 header field 字段:
    DPR、Download、Save-Data、Viewport-Width、WIdth。
  
  如果请求使用了其他标头,同样不再被视为简单请求

3. Content-Type限制: 
  请求类型是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain
```

复杂请求

```
1. Method限制: 
	PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH

2. Header限制: 
	简单请求外的字段

3. Content-Type限制: 
	application/x-www-form-urlencoded、multipart/form-data、text/plain之外
```

*CORS请求头控制字段:*

```
request header 的关键字段:
		Origin
      跨源请求的源站,值为源站的URL(不包含任何路径信息)

    Access-Control-Request-Method	  
      告知服务器,实际请求将使用的方式

    Access-Control-Request-Headers	
      告知服务器,实际请求将携带的自定义请求首部字段

    如:
			Origin: www.eeo.cn
      Access-Control-Request-Method: POST
      Access-Control-Request-Headers: Content-Type
		
		注意:
      Access-Control-Request-Method、Access-Control-Request-Headers
			是在存在跨域请求,浏览器主动添加的行为

  response header 的关键字段:
    Access-Control-Allow-Origin:  
      支持的域名,如果要允许所有域名则设置为 *

    Access-Control-Allow-Methods	 
      支持的请求方式 

    Access-Control-Allow-Headers	 
      支持的headers字段

    Access-Control-Max-Age	       
      预检请求缓存时间,单位为秒
      在此期间,不用发出另一条预检请求
```

*总结:*

options 请求就是预检请求,可用于检测服务器允许的 http 方法。 当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起 OPTIONS 请求,即 CORS 预检请求,服务器若接受该跨域请求,浏览器才继续发起正式请求
  • CORS

    什么是CORS?

    CORS,全称是 "跨域资源共享" (Cross-origin resource sharing)

    一句话总结:

    通过设置 HTTP 响应头来允许浏览器向跨域服务器发送请求,从而解决 AJAX 请求跨域限制问题( 设置请求头来解决跨域问题 )

    CORS产生的原因:

    CORS的产生,源于浏览器的同源策略,限制了网页无法向非同源地址发送AJAX请求。 但实际上,如今很多网页应用都需要向非同源的服务器请求数据,于是为了突破这个限制,允许在服务器一侧配置一些CORS规则,来告诉浏览器允许哪些非同源的请求可以通过

    CORS 的基本思想:

    服务器在响应中提供一个标头(HTTP 头),指示哪些源被允许访问资源。

    浏览器在发起跨域请求时会先发送一个预检请求(OPTIONS 请求)到服务器, 服务器通过设置适当的 CORS 标头来指定是否允许跨域请求,并指定允许的请求源、方法、标头等信息

    CORS的作用:

    1. 允许浏览器向跨域服务器(协议、域名、端口任一不同即跨域)发起请求,从而克服AJAX只能同源使用的限制。

    2. 通过标准化的HTTP头部允许服务器声明哪些源站有权限访问资源。

    一句话总结:解决跨域访问服务器资源

  • 例子

    同域名的情况:

    浏览器Network展示:

请求、响应头参数:

跨域的情况:

1.浏览器 Network展示

  1. 请求头参数:

3.响应头参数:

  • 为什么本地使用 webpack 进行 dev 开发时,不需要服务器端配置 cors 的情况下访问到线上接口?

    当你在本地通过 Ajax 或其他方式请求线上接口时,由于浏览器的同源策略,会出现跨域的问题。 但是在服务器端并不会出现这个问题。

    它是通过 Webpack Dev Server 来实现这个功能。 当你在浏览器中发送请求时,请求会先被 Webpack Dev Server 捕获, 然后根据你的代理规则将请求转发到目标服务器, 目标服务器返回的数据再经由 Webpack Dev Server 转发回浏览器。 这样就绕过了浏览器的同源策略限制,使你能够在本地开发环境中访问线上接口。

    webpackDevServer本身是一个反向代理服务器,服务器之间不存在跨域问题。

  • 为什么有些接口明明是配了CORS策略,但在接口502时,仍然会报跨域的错误?

    502状态码代表 Bad Gateway,表示服务器作为网关或者代理,从上游服务器接收到无效的响应

    在这种情况下,浏览器收到的响应头并不是完整的 CORS 头,不包含 Access-Control-Allow-Origin 等CORS相关头信息。因此浏览器会判断这个响应违反了CORS策略,从而报跨域错误

    还有一些其他的场景:

所以:

不能看到报cors相关的error,就都当跨域处理,也有可能是接口报错了

相关推荐
逆袭的小黄鸭几秒前
JavaScript 异步操作入门指南与基础实践
前端·javascript
意桉1 分钟前
Element Plus 去掉表格外边框
前端·vue.js·elementui·element plus
J船长1 分钟前
gRPC基础,区别REST,使用教程 (Flutter)
前端
cock1 分钟前
JS 数据类型
前端
逾明3 分钟前
使用js创建img加载阿里云oss图片跨域的问题
前端·javascript·浏览器
芝麻糊冲呀5 分钟前
JavaScript 数组方法全解析:从基础到高阶应用
前端
码觉客5 分钟前
在 PDF.js 的 viewer.html 基础上进行改造,实现同一个 PDF 文件在网页中上下拆分显示,并且两部分的标注数据能够实时同步
前端·javascript
freejackman7 分钟前
web前端 html常用标签
前端·html
曲鸟20 分钟前
大环境不好,测试人员该如何快速进阶
前端·后端·面试
sunn。22 分钟前
V-SHOW和箭头函数在VUE项目的踩坑点
前端·javascript·vue.js