Spring Boot 解决跨域问题

在 Spring Boot 中解决跨域问题(CORS)主要有三种常用方式,下面详细说明每种实现方法:

方案一:全局配置(推荐)

在配置类中实现 WebMvcConfigurer 接口,统一配置所有接口的跨域规则:

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")  // 所有接口
                // Spring Boot 2.4+ 使用 allowedOriginPatterns
                .allowedOriginPatterns("*") 
                // 允许的请求方法
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") 
                // 允许的请求头
                .allowedHeaders("*") 
                // 是否允许发送Cookie
                .allowCredentials(true) 
                // 预检请求缓存时间(秒)
                .maxAge(3600); 
    }
}

方案二:控制器注解配置

在单个控制器或方法上使用 @CrossOrigin 注解:

java 复制代码
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
// 类级别配置(整个控制器生效)
@CrossOrigin(origins = "http://localhost:8080", allowCredentials = "true")
public class UserController {

    // 方法级别配置(覆盖类配置)
    @GetMapping("/users")
    @CrossOrigin(maxAge = 1800)
    public List<User> getUsers() {
        return userService.getAllUsers();
    }
}

方案三:过滤器配置(适合WebFlux或特殊需求)

创建自定义CORS过滤器:

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        
        // 允许所有域名(生产环境建议指定具体域名)
        config.addAllowedOriginPattern("*");
        // 允许发送Cookie
        config.setAllowCredentials(true);
        // 允许所有请求头
        config.addAllowedHeader("*");
        // 允许所有方法
        config.addAllowedMethod("*");
        // 预检请求缓存时间
        config.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        
        return new CorsFilter(source);
    }
}

常见问题解决方案

  1. Credentials 与 Origin 冲突问题

    • 现象:前端携带 Cookie 时报错

    • 解决:

      java 复制代码
      // 正确配置
      .allowCredentials(true)
      // 使用 allowedOriginPatterns 替代 allowedOrigins
      .allowedOriginPatterns("http://trusted-domain.com") 
    • 前端配合:

      javascript 复制代码
      fetch(url, {
        credentials: 'include' // 必须
      })
  2. Spring Security 集成问题

    在 Security 配置中启用 CORS:

    java 复制代码
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors() // 启用 CORS
            .and()
            // ... 其他安全配置
    }
  3. OPTIONS 请求被拦截

    • 确保未手动拦截 OPTIONS 方法

    • 在 Security 配置中添加:

      java 复制代码
      .antMatchers(HttpMethod.OPTIONS).permitAll()
  4. 多配置冲突

    • 优先级:过滤器 > 全局配置 > @CrossOrigin
    • 建议整个项目统一使用一种配置方式

最佳实践建议

  1. 开发环境

    使用全局配置 + allowedOriginPatterns("*") 快速开发

  2. 生产环境

    java 复制代码
    .allowedOriginPatterns(
        "https://your-domain.com",
        "https://api.your-domain.com"
    )
  3. 安全加固

    java 复制代码
    // 限制允许的请求头
    .allowedHeaders("Content-Type", "X-Requested-With", "Authorization")
    // 暴露特定响应头
    .exposedHeaders("Custom-Header")

重要提示

  • Spring Boot 2.4.x+ 必须使用 allowedOriginPatterns 替代旧版 allowedOrigins
  • 开启 allowCredentials(true) 时,禁止使用 allowedOriginPatterns("*")(浏览器安全限制),应指定具体域名
相关推荐
uzong5 小时前
后端线上发布计划模板
后端
C雨后彩虹6 小时前
任务最优调度
java·数据结构·算法·华为·面试
uzong6 小时前
软件工程师应该关注的几种 UML 图
后端
heartbeat..6 小时前
Spring AOP 全面详解(通俗易懂 + 核心知识点 + 完整案例)
java·数据库·spring·aop
Jing_jing_X6 小时前
AI分析不同阶层思维 二:Spring 的事务在什么情况下会失效?
java·spring·架构·提升·薪资
上进小菜猪7 小时前
基于 YOLOv8 的 100 类中药材智能识别实战 [目标检测完整源码]
后端
元Y亨H8 小时前
Nacos - 服务发现
java·微服务
微露清风8 小时前
系统性学习C++-第十八讲-封装红黑树实现myset与mymap
java·c++·学习
dasi02278 小时前
Java趣闻
java
码事漫谈8 小时前
AI 技能工程入门:从独立能力到协作生态
后端