Spring Boot 中处理跨域资源

在 Spring Boot 中处理跨域资源共享(CORS)问题,有多种解决方案。以下是几种常见的方法:

方法1:在控制器或方法上添加 @CrossOrigin 注解(推荐)

复制代码
@RestController
@CrossOrigin(origins = "*") // 允许所有源
// 或者指定特定源:@CrossOrigin(origins = "http://localhost:3000")
public class PrintController {
    
    @PostMapping(value = "/v1/multiples", produces = { "application/json" })
    @ResponseStatus(HttpStatus.CREATED)
    @CrossOrigin(origins = "*") // 也可以加在方法级别
    public EntityModel<Map<String, Object>> multiples() {
        return EntityModel.of(overallMap);
    }
}

方法2:全局配置(推荐)

创建全局 CORS 配置类:

复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")  // 允许所有源
                // 或者指定特定源:.allowedOrigins("http://localhost:3000", "http://example.com")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .allowCredentials(false)  // 如果使用 allowCredentials(true),allowedOrigins 不能为 "*"
                .maxAge(3600);
    }
}

方法3:使用 CorsFilter 过滤器

复制代码
@Configuration
public class CorsConfig {
    
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        
        // 设置允许跨域请求的域名
        config.addAllowedOrigin("*");
        // 或者指定特定域名
        // config.addAllowedOrigin("http://localhost:3000");
        
        // 允许跨域请求头
        config.addAllowedHeader("*");
        
        // 允许跨域请求方法
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("OPTIONS");
        
        // 暴露哪些头部信息
        config.addExposedHeader("Authorization");
        
        // 允许凭证
        config.setAllowCredentials(true);
        
        // 预检请求的有效期,单位为秒
        config.setMaxAge(3600L);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        
        return new CorsFilter(source);
    }
}

方法4:在 Spring Security 中配置 CORS

如果使用了 Spring Security:

复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors().and()  // 启用 CORS
            .csrf().disable()  // 如果是 API 接口,通常禁用 CSRF
            .authorizeRequests()
            .antMatchers("/v1/multiples").permitAll()
            .anyRequest().authenticated();
    }
    
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setExposedHeaders(Arrays.asList("Authorization"));
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

方法5:如果遇到多个 CORS 头部问题

如果出现两个 access-control-allow-origin头部,通常是因为多个地方都配置了 CORS。可以:

  1. 检查是否重复配置 :确保只在一个地方配置 CORS

  2. 使用 @Order 注解:指定配置的优先级

    @Configuration
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public class CorsConfig implements WebMvcConfigurer {
    // 配置
    }

  3. 检查 Nginx/Apache 配置:如果前端有代理服务器,确保代理服务器没有重复添加 CORS 头部

最简单的解决方案

对于快速测试,可以直接在控制器类上添加注解:

复制代码
@RestController
@CrossOrigin(origins = "*")
public class PrintController {
    // 你的代码
}

最佳实践建议

  1. 开发环境 :可以使用 *允许所有源

  2. 生产环境:应该指定具体的域名

  3. 如果有前端代理:可以考虑配置代理服务器处理 CORS

  4. 多个地方配置:确保不会在多个地方重复配置 CORS,否则会出现重复头部

选择最适合你项目需求的方案即可。通常方法1或方法2是最简单的解决方案。

相关推荐
Y40900115 分钟前
【多线程】线程安全(1)
java·开发语言·jvm
布局呆星40 分钟前
SpringBoot 基础入门
java·spring boot·spring
mldong1 小时前
Python开发者狂喜!200+课时FastAPI全栈实战合集,10大模块持续更新中🔥
后端
不懂的浪漫1 小时前
mqtt-plus 架构解析(六):多 Broker 管理,如何让一个应用同时连接多个 MQTT 服务
spring boot·分布式·物联网·mqtt·架构
风吹迎面入袖凉1 小时前
【Redis】Redisson的可重入锁原理
java·redis
w6100104661 小时前
cka-2026-ConfigMap
java·linux·cka·configmap
GreenTea1 小时前
从 Claw-Code 看 AI 驱动的大型项目开发:2 人 + 10 个自治 Agent 如何产出 48K 行 Rust 代码
前端·人工智能·后端
不懂的浪漫1 小时前
mqtt-plus 架构解析(十):从内部项目到开源框架,mqtt-plus 的抽取过程与决策
spring boot·mqtt·架构·开源
语戚2 小时前
力扣 968. 监控二叉树 —— 贪心 & 树形 DP 双解法递归 + 非递归全解(Java 实现)
java·算法·leetcode·贪心算法·动态规划·力扣·