网站首页 > 教程文章 正文
"前端调用接口直接报红,
Access-Control-Allow-Origin是什么鬼?"
"明明Postman能调通,浏览器死活提示跨域!"
"配置了CorsFilter为什么还有问题?"
每个全栈开发都躲不过的经典天坑——跨域问题(CORS)。本文从HTTP协议原理出发,手撕Spring Boot中3种根治方案,包含Spring Security特殊场景处理、生产环境安全指南,以及源码层执行顺序解析,拒绝无效配置!
一、跨域本质:3分钟搞懂为什么浏览器要拦你?
划重点:跨域是浏览器的安全策略,与服务端无关!
- 触发条件(同时满足):
- 协议、域名、端口任意一个不同
- 请求包含自定义Header(如Token)
- 使用PUT、DELETE等非简单请求
- 底层原理:
- bash
# 真实场景中的CORS流程
1. 浏览器发送OPTIONS预检请求 →
2. 服务端返回允许的Origin/Methods/Headers →
3. 浏览器放行真实请求
关键点:若预检请求未通过,真实请求根本不会发出!
二、Spring Boot三大解决方案(附避坑指南)
方案1:@CrossOrigin注解 - 适合临时调试
java
@RestController
public class UserController {
// 单个接口允许跨域(默认允许所有来源)
@CrossOrigin(origins = "http://localhost:8080")
@GetMapping("/api/user")
public User getUser() {
return new User("James", 30);
}
// 允许携带Cookie(需前端配合withCredentials)
@CrossOrigin(origins = "*", allowCredentials = "true") // 生产环境慎用!
@PostMapping("/api/login")
public void login() {}
}
坑点:
- 类级别注解会被方法级别覆盖
- 无法设置exposedHeaders(如暴露Authorization头)
方案2:全局配置WebMvcConfigurer- 推荐标准方案
java
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 拦截所有路径
.allowedOrigins("https://your-domain.com") // 生产环境禁用*
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.exposedHeaders("Authorization") // 暴露自定义Header
.allowCredentials(true) // 允许Cookie
.maxAge(3600); // 1小时内不需要预检
}
}
避坑指南:
- 若同时存在Filter方案,此配置可能失效(执行顺序问题)
- allowedOrigins不能同时设置*和allowCredentials=true(浏览器会阻止)
方案3:自定义CorsFilter - 终极控制权
java
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("https://your-domain.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addExposedHeader("Authorization");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
适用场景:
- 需要精细控制跨域逻辑(如动态Origin)
- 整合第三方Filter导致优先级冲突时
三、Spring Security特殊处理:为什么配置了还是报错?
致命陷阱:Spring Security过滤器链优先于CorsFilter!
java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors() // 必须显式启用Spring Security的CORS支持!
.and()
// 其他安全配置...
.csrf().disable();
}
// 关键!需声明CorsConfigurationSource
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.applyPermitDefaultValues(); // 根据需求定制
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}
原理:Spring Security的CorsFilter会覆盖自定义配置,必须通过cors().configurationSource()注入!
四、生产环境安全指南(血泪教训)
- 严禁使用allowedOrigins("*")
- 推荐动态读取白名单:
- java
- 复制
- 下载
- @Value("${cors.allowed-origins}") private String[] allowedOrigins;
- 限制HTTP方法:
- java
.allowedMethods("GET", "POST") // 按需开放
- 严格设置allowedHeaders:
- java
.allowedHeaders("Content-Type", "Authorization") // 拒绝无用Header
- 启用CSRF保护(除非是纯API服务)
五、终极调试技巧
当配置无效时:
- 浏览器Network面板:查看Response Headers是否包含CORS头
- 服务端日志:添加日志拦截器打印请求头
- 源码断点:
- CorsInterceptor(全局配置)
- CorsFilter(过滤器方案)
- DefaultCorsProcessor(处理逻辑)
结语
跨域问题本质是协议规则与框架执行顺序的博弈。掌握这3种方案+安全规则,能解决99%的CORS报错。点赞收藏,下次前端再喊“接口跨域了”,把这篇文章甩给他!
猜你喜欢
- 2025-05-22 详细介绍一下Spring Cloud GateWay中Router的使用?
- 2025-05-22 SpringBoot应用中使用拦截器实现路由转发
- 2025-05-22 谷歌浏览器HTTP不跳转HTTPS设置方法
- 2025-05-22 Java对接DeepSeek API:从零开始打造智能应用
- 2025-05-22 Python小案例70- URL和HTTP协议介绍及语法
- 2025-05-22 HTTPS通信原理及与HTTP的区别
- 2025-05-22 Python中的HTTP访问利器
- 2025-05-22 Spring MVC 底层原理深度解析:从请求到响应的全链路拆解
- 2025-05-22 揭秘HTTP:从诞生到现代的演进之旅
- 2025-05-22 Wuzz - Web 开发与安全测试利器,交互式 HTTP 工具
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- mybatis plus page (35)
- vue @scroll (38)
- 堆栈区别 (33)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)
- redis aof rdb 区别 (33)
- 302跳转 (33)
- http method (35)
- js array splice (33)