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,就都当跨域处理,也有可能是接口报错了

相关推荐
顾平安1 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网1 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工1 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
沈剑心1 小时前
如何在鸿蒙系统上实现「沉浸式」页面?
前端·harmonyos
一棵开花的树,枝芽无限靠近你1 小时前
【PPTist】组件结构设计、主题切换
前端·笔记·学习·编辑器
m0_748237052 小时前
Chrome 关闭自动添加https
前端·chrome
prall2 小时前
实战小技巧:下划线转驼峰篇
前端·typescript
开心工作室_kaic2 小时前
springboot476基于vue篮球联盟管理系统(论文+源码)_kaic
前端·javascript·vue.js
川石教育2 小时前
Vue前端开发-缓存优化
前端·javascript·vue.js·缓存·前端框架·vue·数据缓存
搏博2 小时前
使用Vue创建前后端分离项目的过程(前端部分)
前端·javascript·vue.js