解决跨域问题方案
跨域问题在前后端分离架构下尤为常见,是每个 Web 开发者都会遇到的核心问题。本文将通过原理解析、场景剖析、解决方案详解以及最佳实践等多个维度,帮助开发者全面理解并有效应对跨域问题。
目录
- **一、跨域的本质**
- **1. 同源策略**
- **2. 同源策略的限制范围**
- **3. 为什么需要同源策略**
- **二、跨域问题的常见场景**
- **1. 前后端分离**
- **2. 第三方服务调用**
- **3. 静态资源加载**
- **4. 跨协议请求**
- **三、跨域的解决方案详解**
- **1. CORS(跨域资源共享)**
- **CORS 在 Spring Boot 中的配置**
- **2. 代理服务器转发**
- **3. JSONP(仅支持 GET 请求)**
- **4. iframe + postMessage**
- **5. 后端设置 JSONP API**
- **四、最佳实践**
- **五、总结**
一、跨域的本质
1. 同源策略
跨域问题的根本源于浏览器的同源策略(Same-Origin Policy)。同源策略是浏览器的一种安全机制,用于限制不同源的文档或脚本如何彼此交互,以保护用户的数据安全。
-
同源的定义:协议、域名、端口号必须一致。
属性 示例 1 示例 2 是否同源 协议 http://example.com
https://example.com
否 域名 http://example.com
http://api.example.com
否 端口号 http://example.com:80
http://example.com:8080
否
2. 同源策略的限制范围
同源策略主要限制以下行为:
- Cookie、LocalStorage 和 SessionStorage 的读取
- DOM 和 JavaScript 对象的访问
- AJAX 请求(尤其是跨域数据的访问)
3. 为什么需要同源策略
同源策略主要是为了防止以下安全风险:
- 跨站脚本攻击(XSS):恶意页面通过脚本窃取用户数据。
- 跨站请求伪造(CSRF):利用用户身份对目标网站执行未授权操作。
- 数据劫持:防止不受信任的域窃取敏感信息。
二、跨域问题的常见场景
1. 前后端分离
现代 Web 应用通常采用前后端分离架构,前端通过 AJAX 请求与后端进行交互。当前端和后端运行在不同的域时,会触发跨域问题。例如:
- 前端:
http://localhost:3000
- 后端:
http://localhost:8080
2. 第三方服务调用
前端需要请求第三方 API,例如调用 https://api.example.com
提供的开放服务,这种场景也会引发跨域问题。
3. 静态资源加载
页面运行在 http://example.com
,而静态资源托管在 CDN(如 https://cdn.example.com
)上。
4. 跨协议请求
例如从 HTTP 页面调用 HTTPS 服务。
三、跨域的解决方案详解
1. CORS(跨域资源共享)
CORS 是 W3C 提出的标准解决方案,允许服务端通过设置特定的响应头,告知浏览器允许跨域访问。
- CORS 的关键响应头:
Access-Control-Allow-Origin
:允许的源(如http://example.com
,或*
代表允许所有源)。Access-Control-Allow-Methods
:允许的 HTTP 方法(如GET, POST
)。Access-Control-Allow-Headers
:允许的自定义请求头(如Authorization
)。Access-Control-Allow-Credentials
:是否允许携带凭证(如 Cookie)。Access-Control-Max-Age
:预检请求的缓存时间。
CORS 在 Spring Boot 中的配置
Spring Boot 提供了多种方式支持 CORS:
-
全局配置
使用WebMvcConfigurer
添加全局的 CORS 配置。@Configuration public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("http://example.com").allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("*").allowCredentials(true).maxAge(3600);} }
-
局部配置
在控制器类或方法上使用@CrossOrigin
注解。@RestController @RequestMapping("/api") public class MyController {@CrossOrigin(origins = "http://example.com")@GetMapping("/data")public ResponseEntity<String> getData() {return ResponseEntity.ok("Hello, World!");} }
-
通过过滤器统一配置
使用OncePerRequestFilter
创建全局 CORS 过滤器。@Component public class CORSFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {response.setHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");response.setHeader("Access-Control-Allow-Credentials", "true");filterChain.doFilter(request, response);} }
2. 代理服务器转发
通过代理服务器将跨域请求转发为同源请求,避免跨域问题。
-
开发环境中的前端代理
- React 配置代理:
{"proxy": "http://localhost:8080" }
- Vue 配置代理:
module.exports = {devServer: {proxy: {'/api': {target: 'http://localhost:8080',changeOrigin: true,pathRewrite: { '^/api': '' }}}} };
- React 配置代理:
-
Nginx 反向代理
server {listen 80;server_name example.com;location /api/ {proxy_pass http://backend-service:8080;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;} }
3. JSONP(仅支持 GET 请求)
通过 <script>
标签加载远程数据,并利用回调函数实现跨域通信。
-
前端调用示例:
<script>function handleResponse(data) {console.log(data);} </script> <script src="http://example.com/api?callback=handleResponse"></script>
-
后端返回数据:
handleResponse({"message": "success"});
4. iframe + postMessage
通过嵌入跨域的 iframe,并使用 postMessage
方法实现通信。
- 父页面代码:
const iframe = document.getElementById('myIframe'); iframe.contentWindow.postMessage('hello', 'http://example.com');window.addEventListener('message', (event) => {if (event.origin === 'http://example.com') {console.log(event.data);} });
5. 后端设置 JSONP API
在后端返回一个 JavaScript 函数的调用来传递数据,这种方法兼容性较好但仅适用于简单场景。
四、最佳实践
-
安全性:
- 指定可信任的跨域源,不建议使用通配符(
*
)。 - 对敏感数据接口加强认证和授权控制。
- 指定可信任的跨域源,不建议使用通配符(
-
性能优化:
- 使用
Access-Control-Max-Age
缓存预检请求结果。 - 减少跨域请求次数,合并或延迟请求。
- 使用
-
复杂场景下的组合解决方案:
- 开发阶段使用前端代理,生产环境使用 Nginx 反向代理。
- 配合 CORS 配置和全局过滤器处理复杂跨域请求。
五、总结
跨域问题是浏览器同源策略带来的限制,其根本目的是保护用户数据安全。通过 CORS 配置、全局过滤器、代理服务器等方法,可以灵活解决不同场景下的跨域问题。在实际开发中,应结合项目需求,选择最合适的解决方案,同时注重安全性和性能优化,从而构建更高效、更安全的 Web 应用。
相关文章:
解决跨域问题方案
跨域问题在前后端分离架构下尤为常见,是每个 Web 开发者都会遇到的核心问题。本文将通过原理解析、场景剖析、解决方案详解以及最佳实践等多个维度,帮助开发者全面理解并有效应对跨域问题。 目录 **一、跨域的本质****1. 同源策略****2. 同源策略的限制范…...

云计算介绍_3(计算虚拟化——cpu虚拟化、内存虚拟化、io虚拟化、常见集群策略、华为FC)
计算虚拟化 1.计算虚拟化介绍1.1 计算虚拟化 分类(cpu虚拟化、内存虚拟化、IO虚拟化)1.2 cpu虚拟化1.3 内存虚拟化1.4 IO虚拟化1.5 常见的集群的策略1.6 华为FC 1.计算虚拟化介绍 1.1 计算虚拟化 分类(cpu虚拟化、内存虚拟化、IO虚拟化&#…...

软件工程复习记录
基本概念 软件工程三要素:方法、工具、过程 软件开发方法:软件开发所遵循的办法和步骤,以保证所得到的运行系统和支持的文档满足质量要求。 软件开发过程管理 软件生命周期:可行性研究、需求分析、概要设计、详细设计、编码、测…...

俩Nim游戏
1.给定n堆石子,每堆石子有xi快,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。 问如果两人都采用最优策略ÿ…...

基于超级电容和电池的新能源汽车能量管理系统simulink建模与仿真
目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 超级电容特性 4.2 电池特性 5.完整工程文件 1.课题概述 基于超级电容和电池的新能源汽车能量管理系统simulink建模与仿真。分析不同车速对应的电池,超级电容充放电变化情况。 2.系统仿…...

数据结构——图(遍历,最小生成树,最短路径)
目录 一.图的基本概念 二.图的存储结构 1.邻接矩阵 2.邻接表 三.图的遍历 1.图的广度优先遍历 2.图的深度优先遍历 四.最小生成树 1.Kruskal算法 2.Prim算法 五.最短路径 1.单源最短路径--Dijkstra算法 2.单源最短路径--Bellman-Ford算法 3.多源最短路径--Floyd-…...
002-NoSQL介绍
目录 一、NoSQL 简介 二、NoSQL 特性 三、NoSQL 的工作原理 四、NoSQL 有哪些类型 五、NoSQL数据库与关系型数据库的区别 六、常见的非关系型数据库NOSQL分类 一、NoSQL 简介 NoSQL,全称为Not Only SQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是…...
qt-everywher交叉编译e-src-5.15.2
简化配置的方式: 你完全可以通过直接配置 安装目录、编译链 和 目标架构 来完成交叉编译,而不需要修改 mkspecs 配置。以下是如何通过简化配置来进行交叉编译 Qt 的步骤。 准备交叉编译工具链 首先,确保你已经安装了交叉编译工具链ÿ…...

4.STM32通信接口之SPI通信(含源码)---硬件SPI与W25Q64存储模块通信实战《精讲》
开胃简介 根据上一节对STM32的SPI介绍!本节将进行硬件SPI的实现,片选用软件实现!跟着Whappy走起!W25Q64的驱动层,我们不需要更改,仅仅需要更改一下SPI的协议,即:由软件实现改成硬件…...
生信技能63 - 构建gnomAD变异位点的SQLite查询数据库
将数据量巨大的gnomAD数据库,通过SQLite数据库寻找gnomAD中存在的各种变异注释信息(如等位基因计数,深度,次要等位基因频率等),查询300.000个变量的查询需要大约40秒,通过染色体编号+位置+REF+ALT即可进行快速查询。 1. gnomAD变异注释VCF文件字段 gnomAD VCF各版本包…...
0x0118消息 WM_SYSTIMER
0x0118消息就是WM_SYSTIMER 编辑框出现输入光标时,产生的消息. 0x0118 would be the undocumented WM_SYSTIMER, which appears to be used for caret blinks. 0x0118是一个undocument 消息, 微软没有记录。 但在一些库的源码中可以看到,比如ATL的库文…...
【机器学习】机器学习的基本分类-无监督学习(Unsupervised Learning)
无监督学习(Unsupervised Learning) 无监督学习是一种机器学习方法,主要用于没有标签的数据集。其目标是从数据中挖掘出潜在的结构和模式。常见的无监督学习任务包括 聚类、降维、密度估计 和 异常检测。 1. 无监督学习的核心目标 1.1 聚类…...

[代码随想录09]字符串2的总结
前言 处理字符串主要是有思路,同时总结方法。 题目链接 151. 反转字符串中的单词 - 力扣(LeetCode) 55. 右旋字符串(第八期模拟笔试) 一、翻转字符串里的单词 这个题目的主要思路,代码采用从后往前遍历字…...

java注解(一):什么是注解?什么是元注解?如何自定义注解?注解的原理是什么?
目录 1、什么是注解? 2、什么是元注解 1、Target() 2、Retention() 3、Documented 4、Inherited 3、如何自定义注解以解使用 4、注解的原理 本篇文章主要是介绍注解的概念、原理,以及通过代码演示4种元注解、如何自定义注解。通过反编译的形式进…...

AD20 原理图库更新到原理图
一 点击工具,从库更新。快捷键TL 二 点击完成 三 执行变更,最后点击关闭...

.NET用C#导入Excel数据到数据库
将Excel文件中的数据导入到数据库中不仅能够提升数据处理的效率和准确性,还能极大地促进数据分析和决策制定的过程。尤其在企业级应用中,Excel作为数据输入和初步整理的工具非常普遍,但其功能对于复杂查询、大规模数据管理和跨部门的数据共享…...

小身躯大能量-供热系统通过EtherCAT转Profinet网关进行升级
在现代工业自动化领域,通信技术的进步对于提高系统效率、稳定性和可靠性起着至关重要的作用。EtherCAT(Ethernet for Control Automation Technology)作为一种实时以太网解决方案,因其高性能及成本效益高等特点,在众多…...
Android11.0系统关闭App所有通知
通过广播接收方式,根据包名关闭App所有通知。 packages/apps/Settings$ git diff diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d4c54c6ed8..1ce7d4136f 100644 --- a/AndroidManifest.xmlb/AndroidManifest.xml-106,6 106,7 <uses-permissio…...

# issue 8 TCP内部原理和UDP编程
TCP 通信三大步骤: 1 三次握手建立连接; 2 开始通信,进行数据交换; 3 四次挥手断开连接; 一、TCP内部原理--三次握手 【第一次握手】套接字A∶"你好,套接字B。我这儿有数据要传给你,建立连接吧。" 【第二次…...
力扣100题--移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: […...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...

Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...
41道Django高频题整理(附答案背诵版)
解释一下 Django 和 Tornado 的关系? Django和Tornado都是Python的web框架,但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架,鼓励快速开发和干净、实用的设计。它遵循MVC设计,并强调代码复用。Django有…...