SpringBoot处理跨域请求(CORS)的五种方式

 更新时间:2025年04月20日 08:26:41   作者:北辰alk  
跨域资源共享(CORS)是现代Web开发中常见的问题,Spring Boot提供了多种方式来处理CORS请求,下面我将详细介绍各种实现方式及其适用场景,需要的朋友可以参考下

一、CORS基础概念

1. 什么是跨域请求?

当浏览器从一个域名的网页去请求另一个域名的资源时,如果域名、端口或协议不同,就会产生跨域请求。出于安全考虑,浏览器默认会阻止这类请求。

2. 简单请求 vs 预检请求

类型条件处理方式
简单请求GET/HEAD/POST方法,且Content-Type为text/plain、multipart/form-data或application/x-www-form-urlencoded直接发送请求,带Origin头
预检请求(OPTIONS)不符合简单请求条件的其他请求先发送OPTIONS请求,获得许可后再发送实际请求

二、Spring Boot处理CORS的5种方式

1. 使用@CrossOrigin注解

适用场景:针对单个控制器或方法级别的CORS配置

@RestController
@RequestMapping("/api")
public class MyController {
    
    // 允许特定源的跨域访问
    @CrossOrigin(origins = "https://example.com")
    @GetMapping("/resource")
    public ResponseEntity<String> getResource() {
        return ResponseEntity.ok("跨域资源");
    }
    
    // 更详细的配置
    @CrossOrigin(origins = {"https://example.com", "https://api.example.com"},
                allowedHeaders = {"Content-Type", "Authorization"},
                methods = {RequestMethod.GET, RequestMethod.POST},
                maxAge = 3600)
    @PostMapping("/save")
    public ResponseEntity<String> saveResource() {
        return ResponseEntity.ok("保存成功");
    }
}

2. 全局CORS配置

适用场景:应用级别的统一CORS配置

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")  // 匹配的路径
                .allowedOrigins("https://example.com", "https://api.example.com") // 允许的源
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法
                .allowedHeaders("*") // 允许的请求头
                .exposedHeaders("Authorization", "Content-Disposition") // 暴露的响应头
                .allowCredentials(true) // 是否允许发送cookie
                .maxAge(3600); // 预检请求缓存时间(秒)
        
        // 可以添加多个配置
        registry.addMapping("/public/**")
                .allowedOrigins("*");
    }
}

3. 使用Filter处理CORS

适用场景:需要更底层控制或与非Spring Web环境集成

@Configuration
public class CorsFilterConfig {
    
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        
        // 配置CORS规则
        config.setAllowCredentials(true);
        config.addAllowedOrigin("https://example.com");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setMaxAge(3600L);
        
        // 对所有路径生效
        source.registerCorsConfiguration("/**", config);
        
        FilterRegistrationBean<CorsFilter> bean = 
            new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 设置最高优先级
        
        return bean;
    }
}

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() // 通常CORS和CSRF不能同时使用
            .authorizeRequests()
            .antMatchers("/api/public/**").permitAll()
            .anyRequest().authenticated();
    }
    
    // 提供CORS配置源
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        
        return source;
    }
}

5. 响应头手动设置

适用场景:需要动态控制CORS头

@RestController
public class DynamicCorsController {
    
    @GetMapping("/dynamic-cors")
    public ResponseEntity<String> dynamicCors(HttpServletRequest request, 
                                           HttpServletResponse response) {
        // 根据请求动态设置CORS头
        String origin = request.getHeader("Origin");
        if (isAllowedOrigin(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "GET, POST");
        }
        
        return ResponseEntity.ok("动态CORS响应");
    }
    
    private boolean isAllowedOrigin(String origin) {
        // 实现你的源验证逻辑
        return origin != null && origin.endsWith("example.com");
    }
}

三、CORS配置详解

1. 核心响应头说明

响应头说明
Access-Control-Allow-Origin允许访问的源,可以是具体域名或*(不推荐使用*,特别是需要凭证时)
Access-Control-Allow-Methods允许的HTTP方法(GET, POST等)
Access-Control-Allow-Headers允许的请求头
Access-Control-Expose-Headers浏览器可以访问的响应头
Access-Control-Allow-Credentials是否允许发送cookie(true/false),设为true时Allow-Origin不能为*
Access-Control-Max-Age预检请求结果的缓存时间(秒)

2. 常见问题解决方案

问题1:预检请求(OPTIONS)被拦截

解决方案

  • 确保OPTIONS请求不被安全框架拦截
  • 在Spring Security中配置:
http.cors().and()
    .authorizeRequests()
    .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

问题2:带凭证的请求失败

解决方案

  • 确保allowCredentials(true)和具体的allowedOrigins(不能是*)
  • 前端需要设置withCredentials: true(如axios)

问题3:特定响应头无法获取

解决方案

  • 使用exposedHeaders暴露需要的头:
.exposedHeaders("Custom-Header", "Authorization")

四、最佳实践建议

  • 生产环境不要使用通配符*:明确指定允许的源
  • 合理限制HTTP方法:只开放必要的方法(GET/POST等)
  • 考虑使用环境变量:动态配置允许的源
@Value("${cors.allowed.origins}")
private String[] allowedOrigins;

// 在配置中使用
.allowedOrigins(allowedOrigins)
  • 结合安全框架:Spring Security项目使用专门的CORS配置
  • 测试不同场景:简单请求和预检请求都要测试

五、完整配置示例

@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {
    
    @Value("${app.cors.allowed-origins}")
    private String[] allowedOrigins;
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins(allowedOrigins)
                .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .exposedHeaders("Authorization", "Content-Disposition")
                .allowCredentials(true)
                .maxAge(3600);
                
        registry.addMapping("/public/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "OPTIONS");
    }
    
    // 可选:提供CORS过滤器作为备选
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.applyPermitDefaultValues();
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Arrays.asList(allowedOrigins));
        source.registerCorsConfiguration("/**", config);
        
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}

六、总结

Spring Boot提供了多种灵活的方式来处理CORS:

  1. 简单场景:使用@CrossOrigin注解
  2. 统一配置:实现WebMvcConfigureraddCorsMappings方法
  3. 底层控制:配置CorsFilter
  4. 安全项目:结合Spring Security的cors()配置
  5. 动态需求:手动设置响应头

根据项目需求选择合适的方式,并遵循安全最佳实践,可以有效地解决跨域问题,同时保证应用的安全性。

以上就是SpringBoot处理跨域请求(CORS)的五种方式的详细内容,更多关于SpringBoot处理跨域请求的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot自定义注解如何解决公共字段填充问题

    SpringBoot自定义注解如何解决公共字段填充问题

    本文介绍了在系统开发中,如何使用AOP切面编程实现公共字段自动填充的功能,从而简化代码,通过自定义注解和切面类,可以统一处理创建时间和修改时间,以及创建人和修改人的赋值操作
    2025-03-03
  • SpringMVC + servlet3.0 文件上传的配置和实现代码

    SpringMVC + servlet3.0 文件上传的配置和实现代码

    本篇文章主要介绍了SpringMVC + servlet3.0 文件上传的配置和实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-04-04
  • mybatis 如何利用resultMap复杂类型list映射

    mybatis 如何利用resultMap复杂类型list映射

    这篇文章主要介绍了mybatis 如何利用resultMap复杂类型list映射的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • RocketMQ NameServer架构设计启动流程

    RocketMQ NameServer架构设计启动流程

    这篇文章主要为大家介绍了RocketMQ NameServer架构设计启动流程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • 关于Java中常见的负载均衡算法

    关于Java中常见的负载均衡算法

    这篇文章主要介绍了关于Java中常见的负载均衡算法,负载平衡是一种电子计算机技术,用来在多个计算机、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的,需要的朋友可以参考下
    2023-08-08
  • Spring AI集成DeepSeek的详细步骤

    Spring AI集成DeepSeek的详细步骤

    DeepSeek 作为一款卓越的国产 AI 模型,越来越多的公司考虑在自己的应用中集成,对于 Java 应用来说,我们可以借助 Spring AI 集成 DeepSeek,非常简单方便,本文给大家介绍了Spring AI集成DeepSeek的详细步骤,需要的朋友可以参考下
    2025-02-02
  • java实现酷狗音乐临时缓存文件转换为MP3文件的方法

    java实现酷狗音乐临时缓存文件转换为MP3文件的方法

    这篇文章主要介绍了java实现酷狗音乐临时缓存文件转换为MP3文件的方法,涉及java针对文件操作的相关技巧,需要的朋友可以参考下
    2016-08-08
  • Java实现Jar文件的遍历复制与文件追加

    Java实现Jar文件的遍历复制与文件追加

    这篇文章主要为大家详细介绍了如何利用Java实现Jar文件的遍历复制与文件追加功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-11-11
  • java实现简单银行管理系统

    java实现简单银行管理系统

    这篇文章主要为大家详细介绍了java实现简单银行管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • Java工程中可执行JAR两种打包方式详解

    Java工程中可执行JAR两种打包方式详解

    这篇文章主要为大家详细介绍了Java工程中可执行JAR两种打包方式,一体化可执行包和带外部依赖lib的可执行包,有需要的小伙伴可以学习一下
    2024-04-04

最新评论