Spring Security 集成 React 跨域请求401认证问题排查求助
问题分析与解决方案
核心问题原因
- CORS配置未正确生效:你定义了
CorsConfiguration但未将其注册为Spring Security的CORS配置源,导致自定义规则不生效;同时allowedOrigins设为*并开启allowCredentials=true,这违反浏览器跨域安全规则(带凭证的跨域请求不允许使用通配符域名)。 - 前端未携带认证凭证:Axios跨域请求默认不会携带Cookie,而Spring Security的HTTP Basic认证默认依赖会话Cookie识别用户,后续请求因无认证信息返回401。
- 登录接口与HTTP Basic机制冲突:自定义的
/login接口手动处理认证,但未让前端正确保存或传递认证凭证,和Spring Security自带的HTTP Basic认证逻辑重复。
分步解决方案
1. 修复Spring Security的CORS配置
将自定义的CORS配置注册为CorsConfigurationSource,并指定具体的前端域名(禁止用*):
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.CorsConfigurationSource; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration corsConfig = new CorsConfiguration(); // 替换为你的React实际域名,比如http://localhost:3000 corsConfig.setAllowedOrigins(List.of("http://localhost:3000")); corsConfig.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type")); corsConfig.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH")); corsConfig.setAllowCredentials(true); corsConfig.setExposedHeaders(List.of("Authorization")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", corsConfig); return source; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // 绑定自定义CORS配置源 http.cors(cors -> cors.configurationSource(corsConfigurationSource())); http.csrf().disable(); http.authorizeHttpRequests(auth -> auth .antMatchers("/user/login", "/swagger-resources/**", "/swagger-ui.html", "/webjars/**") .permitAll() .anyRequest().authenticated() ) .httpBasic() .and() .logout(logout -> logout.logoutUrl("/logout")); return http.build(); } }
2. 前端Axios请求开启凭证携带
修改登录和银行列表请求,添加withCredentials: true,确保跨域时传递会话Cookie:
登录请求修改
const login = () => { axios.post("http://localhost:9091/v2/user/login", { user_id:"abc@abc.com", password:"123456" }, { withCredentials: true // 开启跨域凭证携带 }).then(response => { setfirst(response.data); console.log(response.data); }).catch(error => { console.log("error", error); setfirst(error.response); }); };
银行列表请求修改
const bank = () => { axios.get("http://localhost:9091/v2/bank", { withCredentials: true // 开启跨域凭证携带 }).then(response => { console.log(response.data); }).catch(error => { console.log("error", error); }); };
3. 优化认证方式(可选但推荐)
HTTP Basic认证依赖会话Cookie,在前后端分离场景下,更推荐使用JWT Token替代:
- 自定义登录接口验证成功后,生成JWT Token返回给前端。
- 前端将Token保存到
localStorage或sessionStorage。 - 后续所有请求在请求头中携带
Authorization: Bearer <Token>。 - Spring Security配置JWT过滤器,验证Token的合法性。
这种方式无需依赖Cookie,避免跨域凭证传递的问题,更适合前后端分离架构。
额外排查点
- 检查浏览器控制台的跨域错误详情,确认是否是
Access-Control-Allow-Origin不匹配或凭证未携带的问题。 - 验证Spring Security是否正确拦截请求:可以在
SecurityFilterChain中添加日志,确认CORS配置是否生效。 - 生产环境禁止使用
allowedOrigins: "*",必须指定具体的可信域名,避免安全风险。
内容的提问来源于stack exchange,提问作者Rajkumar Kalavacherla
相关产品推荐
相关产品推荐

