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是最简单的解决方案。

相关推荐
深蓝轨迹10 分钟前
@Autowired与@Resource:Spring依赖注入注解核心差异剖析
java·python·spring·注解
不想看见40411 分钟前
C++八股文【详细总结】
java·开发语言·c++
huaweichenai29 分钟前
java的数据类型介绍
java·开发语言
weisian15140 分钟前
Java并发编程--17-阻塞队列BlockingQueue:生产者-消费者模式的最佳实践
java·阻塞队列·blockqueue
奔跑的呱呱牛40 分钟前
GeoJSON 在大数据场景下为什么不够用?替代方案分析
java·大数据·servlet·gis·geojson
爱丽_1 小时前
Pinia 状态管理:模块化、持久化与“权限联动”落地
java·前端·spring
luom01021 小时前
SpringBoot - Cookie & Session 用户登录及登录状态保持功能实现
java·spring boot·后端
黄俊懿1 小时前
【架构师从入门到进阶】第二章:系统衡量指标——第一节:伸缩性、扩展性、安全性
分布式·后端·中间件·架构·系统架构·架构设计
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 骨科术后营养餐推荐系统为例,包含答辩的问题和答案
java
丶小鱼丶2 小时前
数据结构和算法之【栈】
java·数据结构