SpringBoot处理跨域请求(CORS)的五种方式,
分享于 点击 29925 次 点评:140
SpringBoot处理跨域请求(CORS)的五种方式,
目录
- 一、CORS基础概念
- 1. 什么是跨域请求?
- 2. 简单请求 vs 预检请求
- 二、Spring Boot处理CORS的5种方式
- 1. 使用@CrossOrigin注解
- 2. 全局CORS配置
- 3. 使用Filter处理CORS
- 4. Spring Security中的CORS配置
- 5. 响应头手动设置
- 三、CORS配置详解
- 1. 核心响应头说明
- 2. 常见问题解决方案
- 问题1:预检请求(OPTIONS)被拦截
- 问题2:带凭证的请求失败
- 问题3:特定响应头无法获取
- 四、最佳实践建议
- 五、完整配置示例
- 六、总结
一、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:
- 简单场景:使用
@CrossOrigin
注解 - 统一配置:实现
WebMvcConfigurer
的addCorsMappings
方法 - 底层控制:配置
CorsFilter
- 安全项目:结合Spring Security的
cors()
配置 - 动态需求:手动设置响应头
根据项目需求选择合适的方式,并遵循安全最佳实践,可以有效地解决跨域问题,同时保证应用的安全性。
以上就是SpringBoot处理跨域请求(CORS)的五种方式的详细内容,更多关于SpringBoot处理跨域请求的资料请关注3672js教程其它相关文章!
您可能感兴趣的文章:- SpringBoot中处理跨域请求CORS的全面指南
- SpringBoot处理跨域请求的四种方法
- SpringBoot开发技巧之如何处理跨域请求CORS
- Springboot处理配置CORS跨域请求时碰到的坑
- Springboot处理CORS跨域请求的三种方法
用户点评