程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

Spring Boot跨域问题终极解决方案:3种方法根治CORS报错

balukai 2025-05-08 16:49:30 文章精选 5 ℃

"前端调用接口直接报红,
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()注入!


四、生产环境安全指南(血泪教训)

  1. 严禁使用allowedOrigins("*")
  2. 推荐动态读取白名单:
  3. java
  4. 复制
  5. 下载
  6. @Value("${cors.allowed-origins}") private String[] allowedOrigins;
  7. 限制HTTP方法
  8. java

.allowedMethods("GET", "POST") // 按需开放
  1. 严格设置allowedHeaders
  2. java
.allowedHeaders("Content-Type", "Authorization") // 拒绝无用Header
  1. 启用CSRF保护(除非是纯API服务)

五、终极调试技巧

当配置无效时:

  1. 浏览器Network面板:查看Response Headers是否包含CORS头
  2. 服务端日志:添加日志拦截器打印请求头
  3. 源码断点
  4. CorsInterceptor(全局配置)
  5. CorsFilter(过滤器方案)
  6. DefaultCorsProcessor(处理逻辑)

结语

跨域问题本质是协议规则框架执行顺序的博弈。掌握这3种方案+安全规则,能解决99%的CORS报错。点赞收藏,下次前端再喊“接口跨域了”,把这篇文章甩给他!

Tags:

最近发表
标签列表