You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React请求Spring Boot数据库因Spring Security失败,求专家排查

React请求Spring Boot后端因Spring Security认证失败排查

环境

  • Spring Boot后端运行在localhost:7979(IntelliJ默认运行器)
  • React应用运行在localhost:3000(Windows系统的WSL环境)

后端Spring Security配置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig
{
    
    @Resource
    private DataSource dataSource;
 
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception
    {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
        corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
        corsConfiguration.setAllowedOriginPatterns(List.of("*"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setExposedHeaders(List.of("Authorization"));
        
        
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(HttpMethod.POST,  "/api/users").permitAll()
                .requestMatchers("/api/authority").hasAuthority(Constants.ADMIN)
                .anyRequest().authenticated()
            )
            .userDetailsService(userDetailsService)
            .sessionManagement(s -> s
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .cors()
                .configurationSource(request -> corsConfiguration)
                .and()
            .csrf().disable()
            .httpBasic();
               
        http
            .headers()
                .frameOptions().sameOrigin();
        
        return http.build();
    }
}

前端React请求代码(失败版本)

const headers = {}
headers["Authorization"] = "Basic " + btoa("root:root");
const res = await fetch("http://localhost:7979/api/users", headers);
console.log(res);
const data = await res.json();
console.log(data);

日志信息

成功请求日志

2023-01-26T06:04:15.985+02:00 DEBUG 9708 --- [nio-7979-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /api/users
2023-01-26T06:04:16.069+02:00 DEBUG 9708 --- [nio-7979-exec-1] o.s.s.a.dao.DaoAuthenticationProvider    : Authenticated user
2023-01-26T06:04:16.070+02:00 DEBUG 9708 --- [nio-7979-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter  : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=gr.hua.dit.it22023_it22026.models.SecurityUserDetails@6bb270f7, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=172.20.196.70, SessionId=null], Granted Authorities=[ADMIN]]
2023-01-26T06:04:16.071+02:00 DEBUG 9708 --- [nio-7979-exec-1] o.s.security.web.FilterChainProxy        : Secured GET /api/users

失败请求日志

2023-01-26T02:02:23.041+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /api/users
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint@456e1a23
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /error
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
2023-01-26T02:02:23.042+02:00 DEBUG 17932 --- [nio-7979-exec-1] s.w.a.DelegatingAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint@456e1a23

请求详情

General

Request URL: http://localhost:7979/api/users
Request Method: GET
Status Code: 401 
Remote Address: [::1]:7979
Referrer Policy: strict-origin-when-cross-origin

Response Headers

HTTP/1.1 401
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Expose-Headers: Authorization
Access-Control-Allow-Credentials: true
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: SAMEORIGIN
WWW-Authenticate: Basic realm="Realm"
Content-Length: 0
Date: Thu, 26 Jan 2023 11:32:00 GMT
Keep-Alive: timeout=60
Connection: keep-alive

Request Headers

GET /api/users HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,el-GR;q=0.8,el;q=0.7,en-US;q=0.6
Connection: keep-alive
Host: localhost:7979
Origin: http://localhost:3000
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
sec-ch-ua: "Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"

问题分析与解决

从请求详情可明确:失败请求的Request Headers中没有Authorization字段,这是认证失败的核心原因。前端fetch调用方式错误:fetch的第二个参数必须是配置对象,headers需放在该对象的headers属性内,而非直接传递headers对象。

修改后的前端代码:

const headers = {}
headers["Authorization"] = "Basic " + btoa("root:root");
const res = await fetch("http://localhost:7979/api/users", { 
  headers: headers,
  credentials: 'include' // 后端配置了AllowCredentials,需添加此参数确保凭证传递
});
console.log(res);
const data = await res.json();
console.log(data);

后端配置无需调整:已允许Authorization头跨域传递,且/api/users的GET请求需要认证的规则正确。修改后请求会携带Authorization头,Spring Security的BasicAuthenticationFilter将正常处理认证流程,请求即可通过。

内容的提问来源于stack exchange,提问作者Ledrake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:10:24