Spring Boot 跨域问题全解:原理、解决方案与最佳实践
精心整理了最新的面试资料和简历模板,有需要的可以自行获取
点击前往百度网盘获取
点击前往夸克网盘获取
一、跨域问题的本质
1.1 什么是跨域?
跨域(Cross-Origin)问题源于浏览器的同源策略(Same-Origin Policy),该策略限制了一个源的文档或脚本如何与另一个源的资源进行交互。当协议(http/https)、域名或端口任意一项不同时,即被视为跨域请求。
1.2 CORS 工作机制
CORS(Cross-Origin Resource Sharing)是现代浏览器支持的标准机制,通过特定的HTTP头来实现跨域访问控制。其核心流程包括:
- 简单请求:直接发送请求,携带
Origin
头 - 预检请求(Preflight):对非简单请求先发送OPTIONS请求验证
- 凭证请求:携带Cookie等认证信息时需要特殊处理
二、Spring Boot 解决方案大全
2.1 注解方案:@CrossOrigin
最快捷的局部解决方案,适用于单个控制器方法或类
@RestController
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600,allowedHeaders = "*",methods = {RequestMethod.GET, RequestMethod.POST})
public class ApiController {@CrossOrigin // 允许所有源@GetMapping("/data")public ResponseEntity<?> getData() {// ...}
}
2.2 全局配置方案(推荐)
通过实现WebMvcConfigurer
进行统一配置
@Configuration
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://trusted-domain.com").allowedMethods("GET", "POST", "PUT").allowCredentials(true).maxAge(1800);}
}
2.3 过滤器方案
适用于需要细粒度控制的场景
@Bean
public CorsFilter corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration config = new CorsConfiguration();config.setAllowCredentials(true);config.addAllowedOrigin("https://*.example.com");config.addAllowedHeader("*");config.addAllowedMethod("*");source.registerCorsConfiguration("/**", config);return new CorsFilter(source);
}
2.4 Spring Security 集成方案
当项目使用Spring Security时需要额外配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.cors().configurationSource(request -> {CorsConfiguration config = new CorsConfiguration();config.applyPermitDefaultValues();config.addAllowedMethod(HttpMethod.PUT);return config;});// 其他安全配置...}
}
三、进阶配置与最佳实践
3.1 动态源配置
根据环境动态设置允许的源
# application.yml
cors:allowed-origins: - "http://localhost:8080"- "https://prod-domain.com"
@Value("${cors.allowed-origins}")
private String[] allowedOrigins;public void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins(allowedOrigins);
}
3.2 预检请求缓存优化
通过Access-Control-Max-Age
头减少OPTIONS请求次数
config.setMaxAge(3600L); // 单位:秒
3.3 安全增强措施
// 明确指定允许的Header
config.setAllowedHeaders(Arrays.asList("Content-Type", "Authorization","X-Requested-With"
));// 禁用危险配置
config.setAllowCredentials(false); // 除非必要
config.setAllowedOrigins(List.of("https://specific-domain.com")); // 避免使用*
四、常见问题排查指南
4.1 配置未生效的检查清单
- 配置类是否被
@Configuration
注解 - 过滤器顺序是否正确(建议优先级高于认证过滤器)
- Spring Security是否覆盖了CORS配置
- 是否有多余的CORS配置相互覆盖
4.2 浏览器控制台错误解析
- 403 Forbidden:检查Spring Security配置
- Missing CORS headers:确认服务器正确返回CORS头
- Preflight失败:确保OPTIONS请求被正确处理
4.3 生产环境推荐配置
// 生产环境配置示例
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of("https://production-domain.com"));
config.setAllowedMethods(List.of("GET", "POST"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
config.setExposedHeaders(List.of("X-Custom-Header"));
config.setMaxAge(1800L);
config.setAllowCredentials(true);
五、架构层面的解决方案
5.1 API 网关统一处理
通过Nginx配置反向代理解决跨域:
location /api {add_header 'Access-Control-Allow-Origin' $http_origin;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';if ($request_method = 'OPTIONS') {add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain; charset=utf-8';add_header 'Content-Length' 0;return 204;}proxy_pass http://backend-service;
}
5.2 微服务架构中的跨域方案
- 网关层统一处理CORS
- 各服务禁用CORS配置
- 使用JWT等Token验证替代Cookie
六、扩展知识:现代浏览器的CORS策略
特性 | Chrome | Firefox | Safari |
---|---|---|---|
预检请求缓存 | 支持 | 支持 | 部分 |
通配符子域 | 支持 | 支持 | 限制 |
Credentials跨域 | 严格 | 严格 | 严格 |
私有网络访问(Localhost) | 特殊处理 | 特殊处理 | 限制 |
结语
正确配置CORS需要平衡功能需求与安全性。建议遵循最小权限原则,生产环境避免使用通配符(*),定期审查CORS配置。随着Spring框架的迭代更新(当前最新6.x版本),建议关注官方文档获取最新最佳实践。
相关文章:
Spring Boot 跨域问题全解:原理、解决方案与最佳实践
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、跨域问题的本质 1.1 什么是跨域? 跨域(Cross-Origin)问题源于浏览器的同源策略(Same-Origin Policy&…...
vhca_id 简介,以及同 pf, vf 的关系
vhca_id 指的是 Virtual Host Channel Adapter ID(虚拟主机通道适配器编号),它是 NVIDIA(Mellanox)网络设备虚拟化架构中的一个核心概念。 它与 PF(物理功能)、VF(虚拟功能ÿ…...
LlamaIndex 第九篇 Indexing索引
索引概述 数据加载完成后,您将获得一个文档对象(Document)列表(或节点(Node)列表)。接下来需要为这些对象构建索引(Index),以便开始执行查询。 索引(Index) 是一种数据结构,能够让我们快速检索…...
微信小程序原生swiper高度自适应图片,不同屏幕适配,正方形1:1等比例图片轮播
🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回!!) 👉 个人专栏推荐:《前端项目教程以及代码》 ✨一、前言分析 一开始只设了图片的mode="widthFix" st…...

在 C# 中将 DataGridView 数据导出为 CSV
在此代码示例中,我们将学习如何使用 C# 代码将 DataGridView 数据导出到 CSV 文件并将其保存在文件夹中。 在这个程序中,首先,我们必须连接到数据库并从中获取数据。然后,我们将在数据网格视图中显示该数据,…...
解锁 CPU 性能天花板:多维优化策略深度剖析
在数字世界的底层战场,CPU 如同指挥千军万马的将军,掌控着程序运行的节奏与效率。无论是大型服务器应用,还是手机端的轻量化程序,CPU 性能的优化都如同解锁隐藏力量的密码,能让程序在执行效率上实现质的飞跃。本文将深…...
Android SwitchButton 使用详解:一个实际项目的完美实践
Android SwitchButton 使用详解:一个实际项目的完美实践 引言 在最近开发的 Android 项目中,我遇到了一个需要自定义样式开关控件的需求。经过多方比较,最终选择了功能强大且高度可定制的 SwitchButton 控件。本文将基于实际项目中的使用案…...
Kafka如何实现高性能
Kafka如何实现高性能 Kafka之所以能成为高性能消息系统的标杆,是通过多层次的架构设计和优化实现的。 一、存储层优化 1. 顺序I/O设计 日志结构存储:所有消息追加写入,避免磁盘随机写分段日志:将日志分为多个Segment文件&…...

MySQL中表的增删改查(CRUD)
一.在表中增加数据(Create) INSERT [INTO] TB_NAME [(COLUMN1,COLUMN2,...)] VALUES (value_list1),(value_list2),...;into可以省略可仅选择部分列选择插入,column即选择的列, 如图例可以选择仅在valuelist中插入age和id如果不指…...

项目思维vs产品思维
大家好,我是大明同学。 这期内容,我们来聊一下项目思维和产品思维的区别。 项目是实施关键,力求每一步都精准到位;产品则是战略导向,确保所选之路正确无误。若缺乏优异成果,即便按时完成,也只…...

游戏引擎学习第285天:“Traversables 的事务性占用”
回顾并为当天的工作做准备 我们有一个关于玩家移动的概念,玩家可以在点之间移动,而且当这些点移动时,玩家会随之移动。现在这个部分基本上已经在工作了。我们本来想实现的一个功能是:当玩家移动到某个点时,这个点能“…...
基于DWT的音频水印算法
基于离散小波变换(DWT)的音频水印算法是一种结合信号处理与信息隐藏的技术,旨在将版权信息或标识隐蔽地嵌入音频信号中,同时保证不可感知性和鲁棒性。以下是该算法的核心步骤及关键技术点: 1. 算法基本原理 DWT…...
小刚说C语言刷题—1700请输出所有的2位数中,含有数字2的整数
1.题目描述 请输出所有的 2 位数中,含有数字 2 的整数有哪些,每行 1个,按照由小到大输出。 比如: 12、20、21、22、23… 都是含有数字 2的整数。 输入 无 输出 按题意要求由小到大输出符合条件的整数,每行 1 个。…...

文件上传Ⅲ
#文件-解析方案-执行权限&解码还原 1、执行权限 文件上传后存储目录不给执行权限(即它并不限制你上传文件的类型,但不会让相应存有后门代码的PHP文件执行,但是PNG图片是可以访问的) 2、解码还原 数据做存储,解…...
Ubuntu中配置【Rust 镜像源】
本篇主要记录Ubuntu中配置Rust编程环境时,所需要做的镜像源相关的配置 无法下载 Rust 工具链 通过环境变量指定 Rust 的国内镜像源(如中科大或清华源)。 方法一:临时设置镜像 export RUSTUP_DIST_SERVERhttps://mirrors.ustc.e…...
Room数据库
Room数据库 Room是Android Jetpack组件中的一款SQLite数据库抽象层框架,旨在简化本地数据库操作,提供编译时SQL校验、类型与安全、与LiveData/Flow无缝集成等特性。 1. 什么是Room 定义: Room 是 Android Jetpack 提供的一个 ORMÿ…...

基于深度学习的工业OCR数字识别系统架构解析
一、项目场景 春晖数字识别视觉检测系统专注于工业自动化生产监控、设备运行数据记录等关键领域。系统通过高精度OCR算法,能够实时识别设备上显示的关键数据(如温度、压力、计数等),并定时存储至Excel文件中。这些数据对于生产过…...

go-中间件的使用
中间件介绍 Gin框架允许开发者在处理请求的过程中加入用户自己的钩子(Hook)函数这个钩子函数就是中间件,中间件适合处理一些公共的业务逻辑比如登录认证,权限校验,数据分页,记录日志,耗时统计 1.定义全局中间件 pac…...
谷歌曾经的开放重定向漏洞(如今已经修复) -- noogle DefCamp 2024
题目描述: 上周,我决定创建自己的搜索引擎。这有点难,所以我背上了另一个。我也在8000端口上尝试了一些东西。 未发现题目任何交互,但是存在一个加密js const _0x43a57f _0x22f9; (function(_0x3d7d57, _0x426e05) {const _0x16c3fa _0x22f9, _0x3187…...
(7)python开发经验
文章目录 1 找不到资源文件2 使用subprocess执行时有黑色弹窗3 找不到exec4 pyside6-project lupdate的bug5 找不到pyd模块6 pyd模块编码错误7 运行显示Qt platform plugin "windows" in "8 tr()包含的字符串无法被翻译 更多精彩内容👉内容导航 &…...

学习以任务为中心的潜动作,随地采取行动
25年5月来自香港大学、OpenDriveLab 和智元机器人的论文“Learning to Act Anywhere with Task-centric Latent Actions”。 通用机器人应该在各种环境中高效运行。然而,大多数现有方法严重依赖于扩展动作标注数据来增强其能力。因此,它们通常局限于单一…...

15.springboot-控制器处理参数传递
22.springMVC Spring MVC 是非常著名的 Web 应用框架,现在的大多数 Web 项目都采用 Spring MVC。它与 Spring 有着紧 密的关系。是 Spring 框架中的模块,专注 Web 应用,能够使用 Spring 提供的强大功能,IoC , Aop 等等。 Spring…...

半成品的开源双系统VLA模型,OpenHelix-发表于2025.5.6
半成品的开源双系统VLA模型,OpenHelix https://openhelix-robot.github.io/ 0. 摘要 随着OpenVLA的开源,VLA如何部署到真实的机器人上获得了越来越多的关注,各界人士也都开始尝试解决OpenVLA的效率问题,双系统方案是其中一个非…...

网站推荐(第四期)
好久没有推荐过网站了,重拾推荐一波,最近发现这几个确实不错。 某火箭共享账号 官网:https://id.bocchi.vip/ 苹果用户专用,都是买了某火箭的账号,懂得都懂。 这玩意竟然还是个开源项目,项目地址&#x…...

2024 睿抗机器人开发者大赛CAIP-编程技能赛-专科组(国赛)解题报告 | 珂学家
前言 题解 2024 睿抗机器人开发者大赛CAIP-编程技能赛-专科组(国赛),陈越姐姐出题。 国赛比省赛,难度增强了不少,题目就剩下4个题了。 涉及堆栈,hash表,优先队列等高阶数据结构的使用&#x…...

git工具使用详细教程-------命令行和TortoiseGit图形化
下载 git下载地址:https://git-scm.com/downloads TortoiseGit(图形化工具)下载地址:https://tortoisegit.org/download/ 认识git结构 工作区:存放代码的地方 暂存区:临时存储,将工作区的代码…...

Mysql新增
插入一个记录需要的时间由下列因素组成,其中的数字表示大约比例: 连接:(3)发送查询给服务器:(2)分析查询:(2)插入记录:(1x记录大小)插入索引:(1x索引&#x…...

AI Agent开发第64课-DIFY和企业现有系统结合实现高可配置的智能零售AI Agent(上)
开篇 我们之前花了将近10个篇章讲Dify的一些基础应用,包括在讲Dify之前我们讲到了几十个AI Agent的开发例子,我不知道大家发觉了没有,在AI Agent开发过程中我们经常会伴随着这样的一些问题: 需要经常改猫娘;需要经常改调用LLM的参数,甚至在一个流程中有3个节点,每个节点…...

【嵌入式】记一次解决VScode+PlatformIO安装卡死的经历
PlatformIO 是开源的物联网开发生态系统。提供跨平台的代码构建器、集成开发环境(IDE),兼容 Arduino,ESP8266和mbed等。 开源库地址:https://github.com/platformio 在 VScode 中配置 PlatformIO 插件,记录…...
文件系统交互实现
关于之前的搭建看QT控件文件系统的实现-CSDN博客,接下来是对本程序的功能完善,我想着是这样设计的,打开一个目录以后,鼠标选中一个项可以是目录,也可以是文件,右键可以出现一个菜单选择操作,比如…...