解决CORS问题的技术点的原理总结

2 篇文章 0 订阅
2 篇文章 0 订阅

序言-引出问题

本人在毕业之后主要是从事游戏开发的客户端相关工作,由于游戏引擎的跨平台功能,所以在游戏开发完成之后,需要发布的平台经常会包含Web平台(包括desktop Web、Mobile Web)。

打包出来的项目文件的入口都是index.html文件。

但是如果直接双击打开index.html之后,在浏览器上是运行不起来的,都会报以下类似的错误

其中,主要关注这个错误:

from origin 'null' has been blocked by CORS policy

 这个错误引发两个关键点。

origin 'null'

CORS policy

这里首先要解释“CORS”,再解释“origin ''null'”。

CORS

先来个官方解释:

CORS(Cross-Origin Resource Sharing,跨源资源共享)是一种安全机制,防止非同源的域进行数据交互。出现这个错误通常意味着你的前端应用尝试从一个与其自身不同源的域(origin)获取资源,但该域没有明确地给予允许。

 好的,又是一长串用概念拼接起来的文字,读起来费劲。

那么我们再来找重点——非(不)同源的域(origin)

为什么会产出不同源(跨域)问题

所谓不同源,就引出了在Web的开发中,一个经常出现的词,那就是“跨域”。

那么这个域怎么才算同源,怎么才算不同源。

是否同源由CORS的同源策略决定。CORS的同源策略

同源策略的判断规则:

  1. 协议(Protocol)

    • 两个 URL 的协议部分必须完全相同(例如都是 http 或者都是 https)。
  2. 域名(Host)

    • 两个 URL 的主机名部分(域名部分)必须完全相同(例如 www.example.comapi.example.com 不同源)。
  3. 端口(Port)

    • 如果 URL 包含端口号,则两个 URL 的端口号必须完全相同(例如 http://example.com:80http://example.com:8080 不同源)。
    • 如果 URL 没有明确指定端口号,默认端口号为 80http)和 443https)。

只要其中一个同源条件不符合,那么就判定为跨域(即不同源)。

origin 'null'

再来说说这个词的意思,origin 'null'可能表示请求的来源是非明确的或未知的,这可能是因为请求没有正确地设置Origin头部,或者是因为请求是从本地文件系统(file://)发起的。

所以这个解释就符合我们前面双击打开文件这个操作。

如何解决

解决web页面部署跨域的方法可以分为两类,一、需要前端来解决;二、服务器来解决

前端来解决

由前端来解决的问题类型

有以下几种问题是由前端来解决的:

  • System.import

    • System.import(或 import(),ES6 动态导入)这个接口,和其他的 JavaScript 接口和情况也会触发 CORS(跨源资源共享)问题。
  • 动态脚本加载跨域问题

    • 动态创建 <script> 标签加载跨域脚本时,同样受到浏览器的同源策略限制。可以考虑使用 JSONP 或 CORS 解决方案。
  • AJAX 请求跨域问题

    • 使用 XMLHttpRequest 或 Fetch API 发起跨域请求时,需要处理浏览器的同源策略限制。解决方法包括使用 CORS、JSONP、代理服务器等。
  • Cookies 跨域问题

    • 默认情况下,浏览器不会发送跨域请求的 Cookie。如果需要在跨域请求中发送和接收 Cookie,需要在服务器端设置 Access-Control-Allow-Credentialstrue,并在客户端设置 withCredentialstrue
  • LocalStorage 和 IndexedDB 跨域问题

    • 虽然这些本地存储机制通常不直接受到 CORS 的影响,但如果跨域请求获取数据并存储在本地存储中,可能需要考虑安全性和数据隔离的问题。
  • 前端框架或库中的跨域支持

    • 一些前端框架或库可能会提供跨域请求的封装或支持,开发人员需要了解和使用这些功能来简化跨域请求的处理。

其中经常出现的是前三种情况 ,在文章开头的问题就是第二种动态脚本加载跨域问题

那么如何解决前端如何解决以上类型的问题呢?主要有以下两种方式:

  • 使用代理服务器

    • 如果直接在客户端无法修改请求或处理CORS问题,可以考虑在客户端和服务端之间部署代理服务器。代理服务器可以在服务器端发送请求,然后将响应返回给客户端,避免跨域限制。
  • 使用JSONP

    • 对于仅支持 GET 请求的跨域数据获取,可以考虑使用 JSONP。JSONP 利用 <script> 标签没有跨域限制的特性,通过动态创建 <script> 标签来加载数据。

 其中使用代理服务器是最为常见的解决方案,代理服务器又分为正向代理服务器、反向代理服务器、Web服务器等。

其中反向代理服务器又是最为常见的代理服务器,而反向代理服务器又有Nginx、Apache等。

其中Nginx又是最为常见的反向代理服务器,所以我们需要把我们的html页面及所有资源都部署到Nginx的服务器上面去。

Nginx如何解决CORS

Nginx可以解决CORS(跨源资源共享)问题,主要是因为它作为反向代理服务器,具有灵活的配置能力和强大的请求处理功能。以下是几个关键原因:

  1. 添加HTTP响应头: Nginx可以通过配置文件中的add_header指令,动态地添加HTTP响应头。对于CORS来说,主要是通过添加Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers等头部来告知浏览器哪些源、方法和头部是允许的。这使得Nginx能够在代理请求时向响应中注入必要的CORS头部信息。

  2. 处理预检请求(OPTIONS请求): 跨源请求中,浏览器在发送一些特殊类型的请求(如带有自定义头部的请求或非简单请求)之前,会发送一个预检请求(OPTIONS请求)。Nginx能够通过配置在收到这类请求时,正确响应预检请求,包括返回允许的方法、头部等信息,从而使浏览器在正式发送实际请求前获得必要的确认。

  3. 灵活的位置和服务器块配置: Nginx的配置文件允许在不同的位置块(location block)或服务器块(server block)中针对不同的URL路径或虚拟主机配置CORS。这种灵活性使得可以根据需要细粒度地控制CORS策略,以满足不同的业务需求和安全要求。

  4. 性能和可扩展性: Nginx因其高性能和低资源消耗而广受欢迎,能够处理大量并发请求。通过在Nginx层面解决CORS问题,可以减少后端服务器的负担,提高整体系统的性能和可扩展性。

综上所述,Nginx作为反向代理服务器,具备处理HTTP请求和响应的强大功能,使其能够有效地解决CORS问题。通过正确配置CORS相关的HTTP头部和处理预检请求,Nginx能够帮助应用程序和服务在跨源请求中实现安全、可靠的数据交换。

Tips:关于Nginx的更多内容,请自行查询。

服务器来解决

由服务器来解决的问题来源

在正常的Web页面开发流程中,有两个概念比较重要,第一是Web页面的资源地址,第二是Web页面请求接口的服务器地址。

Web页面的资源链接地址往往与Web页面请求接口的服务器地址不一致。

这就是造成这一类CORS问题的主要来源。

服务器解决CORS问题主要方法

服务器通过以下方法来处理CORS(在Go、Java、NodeJs都适用)。

第一、设置Access-Control-Allow-Origin头部

  • 这是最基本的CORS响应头部。通过设置Access-Control-Allow-Origin头部,可以指定允许访问资源的域名或使用通配符 * 表示允许所有域名访问。例如,允许所有域名访问可以这样设置:

Access-Control-Allow-Origin: *

或者指定具体的域名:

Access-Control-Allow-Origin: https://example.com

第二、处理预检请求(OPTIONS请求)

  • 对于某些复杂请求(例如带有自定义头部或使用非简单 HTTP 方法的请求),浏览器会先发送一个 OPTIONS 请求(预检请求)。服务器需要正确响应这个预检请求,包括返回适当的CORS头部和响应状态码(如200 OK)。
  • 设置 Access-Control-Allow-Methods 头部指定允许的 HTTP 方法,如 GET, POST, PUT, DELETE 等。
  • 设置 Access-Control-Allow-Headers 头部指定允许的 HTTP 头部,例如 Content-Type, Authorization 等。

第三、允许发送 Cookie 和 HTTP 认证信息

  • 如果跨域请求需要发送和接收 Cookie 或 HTTP 认证信息,服务器需要设置 Access-Control-Allow-Credentials: true 头部,并在客户端请求中设置 credentials: 'include'

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值