剖析跨域问题始末及其解决方案——前端必备交叉知识(一)

简介: 跨域问题是前端开发中的常见挑战,了解并掌握不同的跨域解决方案能帮助你更高效地进行开发工作。本文对同源策略、跨域以及解决跨域的三种方案: CORS、JSONP、代理等跨域技术进行了介绍。选择合适的跨域解决方案非常重要。 在实际开发中,推荐优先考虑使用 CORS,因为它是现代浏览器支持的标准,且安全性较高。如果服务器无法修改,则可以考虑使用代理。如果是特殊情况,可以使用 JSONP,但要注意安全性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错


作者:watermelo37

涉及领域:Vue、SpingBoot、Docker、LLM、python等

---------------------------------------------------------------------

温柔地对待温柔的人,包容的三观就是最大的温柔。

---------------------------------------------------------------------

image.gif 编辑

剖析跨域问题始末及其解决方案——前端必备交叉知识(一)

image.gif 编辑

       在前端开发的旅程中,跨域问题无疑是一道难以逾越的高山。无论是初入职场的新手,还是经验丰富的老手,都可能在这座山前止步不前。跨域问题不仅在调试阶段频繁出现,更在正式环境的部署中如影随形,让开发人员头疼不已。今天,就让我们一起深入探讨跨域问题的根源,剖析其表现形式,并逐一攻克常见的跨域难题。希望这篇文章能成为你的指南,帮助你全面理解跨域及其解决方案,提升解决实际问题的能力。

一、同源策略与跨域

1、什么是同源策略

       同源策略(Same-Origin Policy) 是浏览器的一种安全机制,目的是为了防止不同来源的文档和脚本相互干扰,避免潜在的安全问题。根据同源策略,同源的资源可以自由交互,而异源的资源则受到严格限制。

       同源的定义是:

源(origin) = 协议 + 域名(ip地址) + 端口

        比如百度的首页链接与搜索“跨域”词条后的链接属于同源,他们的源都是https://www.baidu.com(协议 + 域名 + 端口)

百度首页:https://www.baidu.com/

搜索“跨域”词条:https://www.baidu.com/s?wd=%E8%B7%A8%E5%9F%9F&ie=UTF-8&tn=40020637_15_oem_dg&ch=1

image.gif 编辑

image.gif 编辑

        而百度(https://www.baidu.com/)和百度图片(https://image.baidu.com/)就是异源的,因为域名不同。

       我们在开发中同时启动的前后端项目,假如分别为:http://localhost:8080和http://localhost:8081,它们也是异源的,因为端口号不同。

       还有一种情况就是协议不同,http、https、ws(websocket),这三种常见的协议相互之间都是异源的。

2、违背同源策略(即跨域)会怎么样?

       跨域问题通常发生在你希望从一个域名(比如前端应用)访问另一个域名(比如后端API)时,浏览器会阻止这一行为,除非目标服务器显式声明允许跨域请求。最常见的跨域请求场景是使用 AJAX 向后端API发起请求。

二、为什么会有跨域问题?

1、同源策略的设计初衷

       同源策略(Same-Origin Policy)是浏览器的一个核心安全机制,目的是为了防止恶意网站从用户的浏览器中窃取敏感信息。例如,假设用户在银行网站登录,其浏览器的身份验证信息可能会被一个恶意网站请求并滥用。为了防止这种情况,浏览器就强制实施了同源策略。

       简单点说,你的浏览器会保留很多缓存数据,登录的token也不会立即失效,如果没有同源策略,那么你访问一些特殊的网站,它就可以偷偷读取你其他网站的信息,泄露隐私甚至造成财产经济损失。

2、浏览器如何识别跨域?

       当你从一个页面发起请求(如 AJAX 请求),浏览器会首先检查请求的目标是否与当前页面同源。如果目标是异源,浏览器就会阻止该请求,除非目标服务器明确表示允许跨源请求。这也是为何跨域请求会在开发中带来困扰。

三、现代跨域的解决方案——CORS

       CORS(Cross-Origin Resource Sharing,跨域资源共享)是解决跨域问题的现代标准,广泛应用于当今的前端开发中。

1、CORS 的基本工作原理

       CORS 允许服务器通过 HTTP 响应头来声明哪些源可以访问资源。当浏览器发现目标服务器支持 CORS 时,会发起跨域请求,并在请求头中包含一个 Origin 字段。服务器返回的响应中需要包含 Access-Control-Allow-Origin 字段,告知浏览器该请求是否被允许。

2、CORS 过程

       简单请求:当请求方法是 GET、POST 或 HEAD;请求头符合安全规范(浏览器默认头部字段均符合安全规范,但手动修改后就可能会打破);并且如果有Content-Type,其值必须为“text/plain”、“multipart/form-data”、“application/x-www-form-urlencoded”这三个中的一个。满足以上三个条件,浏览器会直接发出请求。

       下方两个案例分别违反了“请求头符合安全规范”和“Content-Type值类型只能是上述三种之一”的限制要求:

// 修改了请求头
fetch("https://douyin.com", {
  headers: {
    a: 1,
  },
});
// content-type的值类型不属于“text/plain”、“multipart/form-data”、“application/x-www-form-urlencoded”这三个中的一个
fetch("https://douyin.com", {
  method: "POST",
  headers: {
    "content-type": "application/json",
  },
  body: JSON.stringify({ a: 1, b: 2 }),
});

image.gif

      预检请求:如果请求不符合简单请求的条件,浏览器会先发起一个 OPTIONS 请求(预检请求),询问服务器是否允许此类跨域操作。如果服务器返回允许的响应头,浏览器才会继续发起实际的请求。

3、CORS 响应头

  • Access-Control-Allow-Origin:指定哪些源可以访问资源,可以是具体的域名或 *(允许所有源)。
  • Access-Control-Allow-Methods:指定允许的 HTTP 方法,如 GET、POST、PUT 等。
  • Access-Control-Allow-Headers:指定允许的请求头。
  • Access-Control-Allow-Credentials:如果请求需要携带凭证(如 Cookies),则需要设置为 true。

4、关于Cookie 与身份凭证

       在跨域请求中,默认情况下,浏览器不会发送 Cookie。如果需要发送身份凭证(如 cookie、session),则需要设置以下选项:

// xhr
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
// fetch api
fetch(url, {
  credentials: "include",
});

image.gif

       服务器也需要在响应中明确设置:

Access-Control-Allow-Credentials: true

image.gif

       需要特别注意的是,不能设置 Access-Control-Allow-Origin: *,如果是携带凭证的跨域请求,源必须明确指定。

5、关于跨域情况下的响应头

       在跨域访问时,JS 只能拿到一些最基本的响应头,如:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要让服务器把允许浏览器访问的头放入白名单,例如:

Access-Control-Expose-Headers: authorization, otherHeaders

image.gif

四、代理:中间人的妙用

1、代理解决跨域

       如果无法修改目标服务器的 CORS 设置,另一种常见的解决方案是使用代理。代理服务器充当前端与目标服务器之间的中介,接受来自前端的请求,转发给目标服务器,再将响应返回给前端。

       这种方式通常有两种形式:

  • 开发环境代理:在开发时使用本地代理服务器(如 webpack-dev-server 或 vite)解决跨域问题。
  • 生产环境代理:在生产环境中,部署一个专门的代理服务器,转发请求。

       代理的优点是,它无需目标服务器支持 CORS,但也有一些缺点,比如增加了额外的性能开销,代理增加了请求的响应时间;同时维护复杂,需要额外维护代理服务器。

2、代理的示例

       在 vite 中配置代理:

// vite.config.js
export default {
  server: {
    proxy: {
      '/api': '你允许的可跨域的源',
    },
  },
};

image.gif

五、JSONP:传统的跨域解决方案

1、JSONP 的工作原理

       JSONP(JSON with Padding)是一个较早的解决跨域问题的技术。通过动态插入一个 <script> 标签,浏览器可以绕过同源策略,因为 <script> 标签可以跨域加载资源。JSONP 的核心思想是通过回调函数传递数据。

2、JSONP 的缺点

       仅支持 GET 请求:由于 <script> 标签只能发起 GET 请求,JSONP 无法支持其他 HTTP 方法(如 POST)。

       安全问题:JSONP 通过执行返回的 JavaScript 代码来获取数据,这可能带来 XSS(跨站脚本攻击)的风险。

       由于安全问题,JSONP 现在基本上已被 CORS 所取代,除非没有其他选择,否则不应使用。

六、如何选择合适的跨域解决方案?

       选择跨域解决方案时,主要考虑以下因素:

       是否能控制目标服务器:如果能控制目标服务器的 CORS 配置,推荐使用 CORS。

       是否只需要 GET 请求:如果只能使用 GET 请求并且目标服务器不支持 CORS,考虑使用 JSONP。

       开发和生产环境的兼容性:开发环境通常可以使用代理来解决跨域问题,而生产环境则需要考虑使用反向代理或 CORS。

       这里有一份决策图,可以辅助参考如何选择合适的跨域解决方案,其关键在于控制生产环境和开发环境一致,否则部署的时候依然会出现跨域问题:

image.gif 编辑

七、总结

       跨域问题是前端开发中的常见挑战,了解并掌握不同的跨域解决方案能帮助你更高效地进行开发工作。本文对同源策略、跨域以及解决跨域的三种方案: CORS、JSONP、代理等跨域技术进行了介绍。选择合适的跨域解决方案非常重要。

       在实际开发中,推荐优先考虑使用 CORS,因为它是现代浏览器支持的标准,且安全性较高。如果服务器无法修改,则可以考虑使用代理。如果是特殊情况,可以使用 JSONP,但要注意安全性。

       只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

       其他热门文章,请关注:

       极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

       你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

       通过array.filter()实现数组的数据筛选、数据清洗和链式调用

       通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

       通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

       TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

       深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

       el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

       MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver

       Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具

       在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境

       干货含源码!如何用Java后端操作Docker(命令行篇)

相关文章
|
1月前
|
前端开发 JavaScript 应用服务中间件
前端跨域问题解决Access to XMLHttpRequest at xxx from has been blocked by CORS policy
跨域问题是前端开发中常见且棘手的问题,但通过理解CORS的工作原理并应用合适的解决方案,如服务器设置CORS头、使用JSONP、代理服务器、Nginx配置和浏览器插件,可以有效地解决这些问题。选择合适的方法可以确保应用的安全性和稳定性,并提升用户体验。
618 90
|
3月前
|
前端开发 JavaScript Java
前端解决axios请求的跨域问题【2步完成】
本文介绍如何通过前端配置解决跨域问题,主要针对Vue项目中的`vite.config.js`文件进行修改。作者在联调过程中遇到跨域报错
79 1
|
5月前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
101 3
springboot解决js前端跨域问题,javascript跨域问题解决
|
5月前
|
前端开发 JavaScript 安全
揭秘!前端大牛们如何高效解决跨域问题,提升开发效率!
【10月更文挑战第30天】在Web开发中,跨域问题是一大挑战。本文介绍前端大牛们常用的跨域解决方案,包括JSONP、CORS、postMessage和Nginx/Node.js代理,对比它们的优缺点,帮助初学者提升开发效率。
156 4
|
6月前
|
前端开发 JavaScript
乾坤qiankun(微前端)样式隔离解决方案--使用插件替换前缀
乾坤qiankun(微前端)样式隔离解决方案--使用插件替换前缀
1047 8
|
6月前
|
设计模式 前端开发 JavaScript
前端编程的异步解决方案有哪些?
本文首发于微信公众号“前端徐徐”,介绍了异步编程的背景和几种常见方案,包括回调、事件监听、发布订阅、Promise、Generator、async/await和响应式编程。每种方案都有详细的例子和优缺点分析,帮助开发者根据具体需求选择最合适的异步编程方式。
166 1
|
7月前
|
运维 前端开发
前端使用antdesign导出插件跨域问题
前端使用antdesign导出插件跨域问题
110 1
|
8月前
|
开发者 安全 UED
JSF事件监听器:解锁动态界面的秘密武器,你真的知道如何驾驭它吗?
【8月更文挑战第31天】在构建动态用户界面时,事件监听器是实现组件间通信和响应用户操作的关键机制。JavaServer Faces (JSF) 提供了完整的事件模型,通过自定义事件监听器扩展组件行为。本文详细介绍如何在 JSF 应用中创建和使用事件监听器,提升应用的交互性和响应能力。
75 0
|
8月前
|
前端开发 JavaScript 中间件
【前端状态管理之道】React Context与Redux大对决:从原理到实践全面解析状态管理框架的选择与比较,帮你找到最适合的解决方案!
【8月更文挑战第31天】本文通过电子商务网站的具体案例,详细比较了React Context与Redux两种状态管理方案的优缺点。React Context作为轻量级API,适合小规模应用和少量状态共享,实现简单快捷。Redux则适用于大型复杂应用,具备严格的状态管理规则和丰富的社区支持,但配置较为繁琐。文章提供了两种方案的具体实现代码,并从适用场景、维护成本及社区支持三方面进行对比分析,帮助开发者根据项目需求选择最佳方案。
162 0
|
8月前
|
前端开发 JavaScript
【Azure 环境】前端Web通过Azure AD获取Token时发生跨域问题(CORS Error)
【Azure 环境】前端Web通过Azure AD获取Token时发生跨域问题(CORS Error)
114 0
下一篇
oss创建bucket