在 Spring Security 中处理跨域问题(CORS)需要明确配置允许的跨域请求规则,并确保 Spring Security 的过滤器链不会拦截合法的跨域请求。以下是完整的配置步骤和注意事项:
一、跨域问题背景
跨域请求由浏览器的 同源策略(Same-Origin Policy) 引发,需通过 CORS(Cross-Origin Resource Sharing) 机制解决。未正确配置时,前端会遇到以下错误:
Access to XMLHttpRequest at 'http://api.example.com/data' from origin 'http://frontend.com' has been blocked by CORS policy.
二、Spring Security 中的 CORS 配置
1. 定义 CORS 规则
创建一个 CorsConfigurationSource
Bean,配置允许的源、方法、头部等信息:
@Bean
public CorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.setAllowedOrigins(Arrays.asList("http://frontend.com")); // 允许的源configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); // 允许的方法configuration.setAllowedHeaders(Arrays.asList("*")); // 允许的请求头configuration.setAllowCredentials(true); // 允许携带凭证(如 Cookie)UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration); // 应用到所有路径return source;
}
2. 在 Spring Security 中启用 CORS
在安全配置类中通过 http.cors()
启用 CORS:
@Configuration
@EnableWebSecurity
public class SecurityConfig {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.cors() // 启用 CORS 支持.and().authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();return http.build();}@Beanpublic CorsConfigurationSource corsConfigurationSource() {// 上述 CORS 配置return source;}
}
三、处理预检请求(OPTIONS)
浏览器在发送实际请求前会先发送 OPTIONS 预检请求,需确保 Spring Security 允许此类请求:
1. 允许 OPTIONS 请求
在权限配置中放行 OPTIONS
方法:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 允许所有 OPTIONS 请求.anyRequest().authenticated();
2. 禁用 CSRF 保护(可选)
若前端与后端分离且无 Cookie 认证,可禁用 CSRF:
http.csrf().disable();
注意:禁用 CSRF 会降低安全性,需确保其他防护措施到位。
四、完整配置示例
1. 安全配置类
@Configuration
@EnableWebSecurity
public class SecurityConfig {@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.cors().configurationSource(corsConfigurationSource()) // 应用 CORS 配置.and().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 允许 OPTIONS 请求.anyRequest().authenticated().and().formLogin().and().httpBasic().and().csrf().disable(); // 根据需求决定是否禁用 CSRFreturn http.build();}@Beanpublic CorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.setAllowedOrigins(Arrays.asList("http://frontend.com"));configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-Requested-With"));configuration.setAllowCredentials(true);UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration);return source;}
}
2. 全局 CORS 配置(替代方案)
通过 WebMvcConfigurer
添加全局 CORS 规则:
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("http://frontend.com").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS").allowedHeaders("*").allowCredentials(true);}
}
注意:需同时启用 Spring Security 的 CORS 支持(http.cors()
)。
五、常见问题排查
1. 预检请求返回 403
• 原因:OPTIONS 请求被 Spring Security 拦截。
• 解决:确保配置中允许 OPTIONS 请求:
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
2. 响应头缺失 CORS 信息
• 原因:Spring Security 过滤器链未正确处理 CORS。
• 解决:确认 http.cors()
已启用,并检查 CorsConfigurationSource
配置。
3. 携带 Cookie 时跨域失败
• 条件:前端需设置 withCredentials: true
,且后端配置:
configuration.setAllowCredentials(true);
• 限制:allowedOrigins
不能为 *
,需明确指定域名。
六、安全建议
- 严格限制来源:避免使用
allowedOrigins("*")
,明确指定可信域名。 - 启用 HTTPS:跨域请求应通过 HTTPS 传输,防止敏感信息泄露。
- 按需开放方法:仅允许必要的 HTTP 方法(如 GET、POST)。
- 监控跨域请求:记录异常跨域访问,及时识别攻击行为。
总结
在 Spring Security 中处理跨域问题的关键在于:
- 定义清晰的 CORS 规则:通过
CorsConfigurationSource
或WebMvcConfigurer
配置。 - 允许 OPTIONS 预检请求:确保 Spring Security 放行预检请求。
- 按需调整安全策略:如禁用 CSRF 或限制允许的请求头。
正确配置后,前端应用可安全地与后端 API 跨域通信,同时保持系统的整体安全性。