解决跨域问题方案
跨域问题在前后端分离架构下尤为常见,是每个 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.comhttps://example.com否 域名 http://example.comhttp://api.example.com否 端口号 http://example.com:80http://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] 输出: […...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
GraphRAG优化新思路-开源的ROGRAG框架
目前的如微软开源的GraphRAG的工作流程都较为复杂,难以孤立地评估各个组件的贡献,传统的检索方法在处理复杂推理任务时可能不够有效,特别是在需要理解实体间关系或多跳知识的情况下。先说结论,看完后感觉这个框架性能上不会比Grap…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...
