Springboot跨域失败,配置无效,原因出自SpringSecurity!

本文详细解析了在SpringBoot项目中使用SpringSecurity时遇到的跨域问题,并提供了具体的解决方案,包括如何在WebSecurityConfigurerAdapter中正确配置跨域。

虽然我们在WebMvcConfigurer中设置跨域,但是如果WebSecurityConfigurerAdapter中不设置http.cors(),会导致一个的问题:
如果一个需要被spring security过滤器验证的请求,比如对url“/getInfo”的请求,如果这个请求没有通过验证,比如没有携带token或token不正确,
导致没有给该请求发放authentication,那么这个请求会在后续的Authentication过滤器中被认定鉴权失败,直接返回response给客户端。
这种情况下请求将不会交给WebMvcConfigurer的跨域过滤器,
而WebMvcConfigurer的跨域过滤器会给response header中添加“Access-Control-Allow-Origin”字段,
该字段表示服务器接收此Origin的跨域请求。
由于该请求不会经过WebMvcConfigurer的过滤器,因此响应头中不会携带“Access-Control-Allow-Origin”字段,
导致虽然请求正确在服务器处理了,也把响应发回给浏览器了,但是浏览器认为服务器不接受该地址的跨域请求,
不会将response传递给页面脚本,并且提示该服务器禁止此Origin的跨域请求
故在SpringBoot中使用Spring Security,需要在WebSecurityConfigurerAdapter和WebMvcConfigurer中同时开启跨域。

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {		//不要忘记配置跨域!
        http.cors().and().csrf().disable();
        ...
    }
 
}

感谢这位大哥的帮助才解决这个问题!
这是原文链接:
https://blog.youkuaiyun.com/mr_orange_klj/article/details/108984354

<think> 我们正在解决Spring Boot问题与Spring Security冲突的修复方法。 根据用户需求,他遇到了在配置后,由于Spring Security的存在导致域配置不生效的情况。 常见原因Spring Security的过滤器链会覆盖或忽略域配置,因此需要额外配置。 解决方案通常有两种: 1. 在Spring Security配置中显式启用CORS支持,并配置CORS过滤器。 2. 调整过滤器的顺序,确保CORS过滤器在Spring Security过滤器之前。 具体步骤: 方法一:在Spring Security配置中启用CORS 步骤: a. 确保已经有一个全局的CORS配置(例如通过`@CrossOrigin`注解或`WebMvcConfigurer`)。 b. 在Spring Security配置类中,调用`cors()`方法启用CORS支持。 示例代码: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .cors() // 启用CORS支持 .and() // ... 其他配置(如授权、认证等) } // 可选:如果你没有使用全局的CORS配置(通过WebMvcConfigurer),可以在这里定义一个CorsConfigurationSource @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000")); // 允许的来源 configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); // 允许的方法 configuration.setAllowedHeaders(Arrays.asList("*")); // 允许的头部 configuration.setAllowCredentials(true); // 允许凭据(如cookies) UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); // 对所有路径生效 return source; } } ``` 注意:如果已经在其他地方(如`WebMvcConfigurer`)配置全局CORS,那么只需要在`SecurityConfig`中调用`.cors()`即可,不需要再定义`corsConfigurationSource`。但如果同时定义了,Spring Security会使用自己配置的`corsConfigurationSource`。 方法二:如果方法一不生效,可以尝试自定义CORS过滤器并调整顺序 步骤: 创建一个CORS过滤器,并将其置于Spring Security过滤器之前。 示例代码: 首先,创建一个CORS配置的过滤器(也可以直接使用Spring提供的`CorsFilter`): ```java @Configuration public class CorsFilterConfig { @Bean public FilterRegistrationBean<CorsFilter> corsFilter() { // 创建CORS配置 CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); // 允许凭证(cookies) config.addAllowedOrigin("http://localhost:3000"); // 允许的源 config.addAllowedHeader("*"); // 允许所有头 config.addAllowedMethod("*"); // 允许所有方法(GET, POST等) // 配置源(对所有路径生效) UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); // 创建过滤器 FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source)); bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 设置最高优先级,确保在Spring Security过滤器之前执行 return bean; } } ``` 为什么需要设置最高优先级?因为Spring Security的过滤器链(如`UsernamePasswordAuthenticationFilter`)可能会在CORS过滤器之前执行,从而拒绝请求。 另外,注意如果同时使用了方法一和方法二,可能会造成两次CORS处理,通常只需要一种方法即可。 根据用户提供的引用[1]和[2],他们可能遇到了Spring Security版本问题,因此建议使用最新的稳定版本。如果用户遇到的是安全漏洞问题(如引用[2]提到的CVE-2022-229),那么升级Spring Security版本是必要的。 因此,在解决Spring Security冲突时,建议: 1. 升级Spring Security到安全版本(如引用[1]中提到的5.7.4,引用[2]中提到的5.6.3,但注意5.6.3可能存在漏洞,建议使用最新版本)。 2. 采用上述方法之一配置CORS。 最后,请注意:如果请求中需要携带认证信息(如cookies),则必须设置`setAllowCredentials(true)`,并且不能使用`allowedOrigins("*")`,而应该指定具体的名(如`setAllowedOrigins(Arrays.asList("http://localhost:3000"))`)。 总结: 在Spring Boot中解决Spring Security冲突的关键在于在Spring Security配置中启用CORS并正确配置CORS源,或者通过一个高优先级的CORS过滤器来处理请求。 希望这些方法能帮助用户解决问题。 生成相关问题: </think> ### Spring Boot 解决Spring Security 冲突的方法 在 Spring Boot配置时,**Spring Security 会覆盖全局 CORS 设置**,导致域配置失效。以下是完整的解决方案: --- #### 解决方案 1️⃣:在 Spring Security 配置中启用 CORS(推荐) **核心原理**:通过 `HttpSecurity` 显式启用 CORS 支持 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .cors() // 关键:启用 CORS 支持 .and() // 其他安全配置 .authorizeRequests() .antMatchers("/api/public/**").permitAll() .anyRequest().authenticated(); } // 配置 CORS 规则(可选) @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("http://localhost:3000")); config.setAllowedMethods(Arrays.asList("GET", "POST")); config.setAllowCredentials(true); // 允许凭证(如 cookies) UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); // 应用到所有路径 return source; } } ``` > ✅ **关键点**: > - `.cors()` 激活 Spring Security 的 CORS 过滤器 > - `corsConfigurationSource()` 定义具体规则(如不定义则使用全局配置) --- #### 解决方案 2️⃣:调整全局配置优先级 **核心原理**:确保 CORS 过滤器在 Security 过滤器之前执行 ```java @Configuration public class CorsConfig { // 手动注册 CORS 过滤器并设置最高优先级 @Bean public FilterRegistrationBean<CorsFilter> corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Collections.singletonList("*")); config.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE")); config.setAllowedHeaders(Collections.singletonList("*")); source.registerCorsConfiguration("/**", config); FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source)); bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 关键:最高优先级 return bean; } } ``` --- #### 解决方案 3️⃣:修复安全漏洞冲突 若遇到因安全漏洞修复导致的冲突(如引用[2]中的 CVE-2022-229): ```xml <!-- pom.xml 中升级 Spring Security --> <properties> <spring-security.version>5.7.4</spring-security.version> <!-- 使用安全版本 --> </properties> ``` > 升级后需重新测试域配置,某些安全补丁可能修改 CORS 处理逻辑[^2]。 --- #### 📌 验证技巧 1. **检查过滤器顺序**: ```bash # 启动日志中查看过滤器链 o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 o.s.security.web.FilterChainProxy : /api/**: OrderedFilter: WebAsyncManagerIntegrationFilter OrderedFilter: SecurityContextPersistenceFilter OrderedFilter: HeaderWriterFilter OrderedFilter: CorsFilter # 确保出现在 Security 过滤器之前 ... ``` 2. **测试请求**: ```bash curl -I -H "Origin: http://localhost:3000" http://your-api/api/data # 检查返回头是否包含: Access-Control-Allow-Origin: http://localhost:3000 ``` --- #### 常见错误排查 | 现象 | 原因 | 修复方案 | |------|------|----------| | `CORS preflight` 请求 403 错误 | Spring Security 拦截 OPTIONS 请求 | 在配置中添加 `.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()` | | 请求被拒但 Postman 正常 | 浏览器同源策略限制 | 检查 `Access-Control-Allow-Origin` 头是否精确匹配 | | 登录后失效 | 未启用凭证支持 | 配置 `config.setAllowCredentials(true)` 且不能使用 `*` 名 | > ⚠️ **安全提示**:生产环境避免使用 `setAllowedOrigins("*")`,应明确指定可信名[^1]。 --- #### 最佳实践总结 1. **优先使用方案 1**:通过 `.cors()` 集成最可靠 2. **升级安全依赖**:避免已知漏洞导致的冲突[^2] 3. **严格名控制**:禁用通配符 `*` 的 `Access-Control-Allow-Origin` 4. **测试预检请求**:确保 OPTIONS 方法不被拦截 > 完整示例代码:[Spring Security CORS 官方文档](https://docs.spring.io/spring-security/reference/servlet/integrations/cors.html) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值