Spring Security安全配置:CORS跨域资源共享策略
【免费下载链接】spring-security Spring Security 项目地址: https://gitcode.com/gh_mirrors/spr/spring-security
1. 跨域资源共享(CORS)基础
跨域资源共享(Cross-Origin Resource Sharing,CORS)是一种浏览器安全机制,用于控制不同源(协议、域名或端口不同)的网页如何相互访问资源。当前端应用(如React、Vue)与后端API部署在不同域名时,浏览器会实施同源策略限制跨域请求,此时需要通过CORS策略明确授权允许的跨域行为。
1.1 CORS核心概念
| 术语 | 定义 | 示例 |
|---|---|---|
| 源(Origin) | 协议+域名+端口的组合 | https://example.com:443 |
| 简单请求 | 满足特定条件的GET/POST请求 | Content-Type: application/x-www-form-urlencoded |
| 预检请求(Preflight) | 复杂请求前的OPTIONS探测请求 | 带自定义头的PUT请求 |
| 跨域凭证 | 是否允许跨域请求携带Cookie | withCredentials: true |
1.2 Spring Security中的CORS处理流程
2. Spring Security CORS配置实现
Spring Security通过CorsConfigurer提供CORS配置能力,核心类位于org.springframework.security.config.annotation.web.configurers.CorsConfigurer,其工作原理是集成Spring Web的CorsFilter到安全过滤器链。
2.1 基础配置方式
2.1.1 Java配置方式
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 启用CORS配置
.cors(cors -> cors
// 配置CORS源
.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
// 允许的源(生产环境建议指定具体域名)
config.setAllowedOrigins(Arrays.asList("https://frontend.example.com"));
// 允许的HTTP方法
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
// 允许的请求头
config.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
// 暴露的响应头
config.setExposedHeaders(Arrays.asList("Custom-Header"));
// 预检请求缓存时间(秒)
config.setMaxAge(3600L);
// 是否允许携带凭证
config.setAllowCredentials(true);
// 应用到所有路径
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
})
)
// 其他安全配置
.csrf(csrf -> csrf.disable()); // 生产环境需谨慎处理CSRF
return http.build();
}
}
2.1.2 基于Bean的配置方式
@Configuration
public class CorsConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// 允许所有源(开发环境测试用,生产环境禁止)
configuration.setAllowedOriginPatterns(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 对/api/**路径应用CORS配置
source.registerCorsConfiguration("/api/**", configuration);
return source;
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 使用CorsConfigurationSource bean
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(csrf -> csrf.disable());
return http.build();
}
}
2.2 关键配置参数详解
CorsConfiguration类提供了丰富的配置选项,以下是生产环境常用参数:
| 参数 | 类型 | 说明 | 安全建议 |
|---|---|---|---|
| allowedOrigins | List | 允许的源域名列表 | 避免使用*,指定具体域名 |
| allowedOriginPatterns | List | 允许的源域名模式 | Spring 5.3+支持,如https://*.example.com |
| allowedMethods | List | 允许的HTTP方法 | 遵循最小权限原则,只开放必要方法 |
| allowedHeaders | List | 允许的请求头 | 避免使用*,明确指定所需头 |
| exposedHeaders | List | 允许暴露的响应头 | 仅暴露前端需要访问的头 |
| allowCredentials | boolean | 是否允许跨域凭证 | 设为true时,allowedOrigins不能为* |
| maxAge | Long | 预检请求缓存时间(秒) | 建议设置3600以上减少预检请求次数 |
3. 高级场景配置
3.1 多路径差异化配置
@Bean
public CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// 公开API配置
CorsConfiguration publicConfig = new CorsConfiguration();
publicConfig.setAllowedOriginPatterns(Arrays.asList("*"));
publicConfig.setAllowedMethods(Arrays.asList("GET"));
publicConfig.setMaxAge(86400L);
source.registerCorsConfiguration("/api/public/**", publicConfig);
// 私有API配置
CorsConfiguration privateConfig = new CorsConfiguration();
privateConfig.setAllowedOrigins(Arrays.asList("https://admin.example.com"));
privateConfig.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
privateConfig.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
privateConfig.setAllowCredentials(true);
privateConfig.setMaxAge(3600L);
source.registerCorsConfiguration("/api/private/**", privateConfig);
return source;
}
3.2 与Spring MVC CORS的协同
当同时使用Spring MVC的@CrossOrigin注解和Spring Security CORS时,Security的CORS配置优先级更高。推荐统一通过Security配置全局CORS策略,避免配置冲突。
// Spring MVC控制器(局部CORS配置)
@RestController
@RequestMapping("/api")
public class ApiController {
// 仅当Security未配置CORS时生效
@CrossOrigin(origins = "https://legacy-frontend.example.com")
@GetMapping("/legacy-data")
public ResponseEntity<?> getLegacyData() {
return ResponseEntity.ok("Legacy data");
}
}
3.3 预检请求处理
Spring Security会自动处理预检请求(OPTIONS方法),无需额外配置。但需确保:
- 允许OPTIONS方法在
allowedMethods中 - 预检请求不被其他安全机制拦截
// 确保OPTIONS请求不被拦截
http
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated()
);
4. 常见问题与解决方案
4.1 跨域请求仍被拒绝
问题表现
Access to fetch at 'https://api.example.com/data' from origin 'https://frontend.example.com'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
排查步骤
- 确认CORS配置是否被正确应用
- 检查
allowedOrigins是否包含请求源 - 验证
CorsFilter是否被加入过滤器链
// 调试技巧:检查CORS配置是否生效
@Bean
public FilterRegistrationBean<CorsFilter> corsFilterRegistration(CorsConfigurationSource configSource) {
FilterRegistrationBean<CorsFilter> registration = new FilterRegistrationBean<>(new CorsFilter(configSource));
registration.setName("corsFilter");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE); // 确保优先级最高
return registration;
}
4.2 带凭证的跨域请求失败
问题根源
当allowCredentials=true时,allowedOrigins不能设置为*,必须指定具体域名。
正确配置
// 错误配置
config.setAllowedOrigins(Arrays.asList("*"));
config.setAllowCredentials(true); // 此时会导致跨域失败
// 正确配置
config.setAllowedOrigins(Arrays.asList("https://frontend.example.com"));
config.setAllowCredentials(true);
4.3 预检请求403错误
解决方案
确保预检请求不被认证机制拦截:
http
.authorizeHttpRequests(auth -> auth
// 允许所有预检请求
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 其他请求需要认证
.anyRequest().authenticated()
);
5. 生产环境最佳实践
5.1 安全加固措施
| 安全措施 | 实现方式 |
|---|---|
| 限制源域名 | 使用allowedOriginPatterns替代allowedOrigins,如https://*.example.com |
| 最小权限原则 | 仅开放必要的HTTP方法和请求头 |
| 凭证保护 | 启用allowCredentials时严格限制源域名 |
| 预检缓存 | 设置合理的maxAge减少预检请求(建议86400秒) |
| HTTPS强制 | 所有跨域通信使用HTTPS,避免中间人攻击 |
5.2 监控与日志
@Component
public class CorsLoggingFilter extends OncePerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(CorsLoggingFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
// 记录跨域请求信息
if (request.getHeader("Origin") != null) {
logger.info("CORS Request - Origin: {}, Method: {}, Path: {}",
request.getHeader("Origin"),
request.getMethod(),
request.getRequestURI());
}
filterChain.doFilter(request, response);
}
}
// 注册过滤器
@Bean
public FilterRegistrationBean<CorsLoggingFilter> corsLoggingFilter() {
FilterRegistrationBean<CorsLoggingFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new CorsLoggingFilter());
registration.addUrlPatterns("/*");
registration.setName("corsLoggingFilter");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
5.3 配置示例:生产环境CORS策略
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
// 生产环境指定具体域名
config.setAllowedOriginPatterns(Arrays.asList(
"https://app.example.com",
"https://admin.example.com"
));
// 仅允许必要HTTP方法
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
// 限制请求头
config.setAllowedHeaders(Arrays.asList(
"Authorization",
"Content-Type",
"Accept-Language"
));
// 暴露必要响应头
config.setExposedHeaders(Arrays.asList("X-Request-ID", "X-RateLimit-Remaining"));
// 启用凭证支持
config.setAllowCredentials(true);
// 预检请求缓存24小时
config.setMaxAge(86400L);
// 应用到API路径
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", config);
return source;
}
6. 总结与展望
CORS配置是Web应用安全的重要环节,Spring Security提供了灵活而强大的CORS支持机制。通过合理配置,可以在保障安全的同时提供良好的跨域体验。随着Web应用架构的演进,未来CORS配置可能会更加自动化,例如通过服务发现自动配置允许的源,但当前仍需开发人员明确配置安全策略。
在实施CORS时,应始终遵循最小权限原则,避免过度开放导致安全风险。同时,结合监控和日志系统,及时发现和解决跨域相关问题,确保应用在安全与可用性之间取得平衡。
【免费下载链接】spring-security Spring Security 项目地址: https://gitcode.com/gh_mirrors/spr/spring-security
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



