在 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.
创建一个 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;
}
在安全配置类中通过 http.cors() 启用 CORS:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors() // 启用 CORS 支持
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
// 上述 CORS 配置
return source;
}
}
浏览器在发送实际请求前会先发送 OPTIONS 预检请求,需确保 Spring Security 允许此类请求:
在权限配置中放行 OPTIONS 方法:
http
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 允许所有 OPTIONS 请求
.anyRequest().authenticated();
若前端与后端分离且无 Cookie 认证,可禁用 CSRF:
http.csrf().disable();
注意:禁用 CSRF 会降低安全性,需确保其他防护措施到位。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public 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(); // 根据需求决定是否禁用 CSRF
return http.build();
}
@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("Authorization", "Content-Type", "X-Requested-With"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
通过 WebMvcConfigurer 添加全局 CORS 规则:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://frontend.com")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}
}
注意:需同时启用 Spring Security 的 CORS 支持(http.cors())。
• 原因:OPTIONS 请求被 Spring Security 拦截。
• 解决:确保配置中允许 OPTIONS 请求:
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
• 原因:Spring Security 过滤器链未正确处理 CORS。
• 解决:确认 http.cors() 已启用,并检查 CorsConfigurationSource 配置。
• 条件:前端需设置 withCredentials: true,且后端配置:
configuration.setAllowCredentials(true);
• 限制:allowedOrigins 不能为 *,需明确指定域名。
allowedOrigins("*"),明确指定可信域名。在 Spring Security 中处理跨域问题的关键在于:
CorsConfigurationSource 或 WebMvcConfigurer 配置。正确配置后,前端应用可安全地与后端 API 跨域通信,同时保持系统的整体安全性。