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

相关推荐
ping某29 分钟前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
JustHappy34 分钟前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
uhakadotcom43 分钟前
在python 的 工程化架构中 ,什么是 薄包装器层?
后端·面试·github
唐青枫5 小时前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
用户1474853079745 小时前
CodeX使用Skill生成游戏美术和音乐资源,一分钟入门
后端
Melody1235 小时前
用 abort 中断 AI 流式请求,我之前做错了
后端
onething3656 小时前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 5 —— SSE 流式输出 + 打字机效果
人工智能·后端·全栈
一个做软件开发的牛马6 小时前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261356 小时前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
码事漫谈6 小时前
AI 编程的「三体」架构:OpenSpec + Superpowers + GStack 如何让一个开发者撑起整个研发团队
后端