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

已认证用户访问API私有端点返回403 Forbidden排查求助

问题

已完成认证的用户访问API私有端点时,始终返回403 Forbidden错误。调试发现UserDetails已成功添加到SecurityContext,但后续doFilter流程似乎导致认证失效,怀疑问题出在JwtAuthenticationFilter中。

JwtAuthenticationFilter 代码:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    final String token = getTokenFromRequest(request);
    final String username;
    if (token == null) {
        filterChain.doFilter(request, response);
        return;
    }
    username = jwtService.getUsernameFromToken(token);
    if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (jwtService.isTokenValid(token, userDetails)) {
            UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                    userDetails,
                    null,
                    userDetails.getAuthorities());
            authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authToken);
        }
    }
    filterChain.doFilter(request, response);
}

SecurityConfig 代码:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final AuthenticationProvider authProvider;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf->
                csrf.disable())
            .authorizeHttpRequests(authRequest ->
                authRequest
                    .requestMatchers("/auth/**").permitAll()
                    .anyRequest().authenticated()
            )
            .sessionManagement(sessionManager ->
                sessionManager.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authenticationProvider(authProvider)
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
    }
}

DEBUG 级别日志:

2024-07-01T11:50:08.830-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing POST /api/v1/demo/
Hibernate: select u1_0.id,u1_0.password,u1_0.role,u1_0.username from wluser u1_0 where u1_0.username=?
2024-07-01T11:50:33.405-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Secured POST /api/v1/demo/
2024-07-01T11:50:33.442-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing POST /error
2024-07-01T11:50:33.443-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2024-07-01T11:50:33.444-07:00 DEBUG 15809 --- [WorkLogAPI] [nio-8080-exec-3] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
分析与解决

从日志能看出核心问题:/api/v1/demo/请求已被成功认证(日志显示Secured POST /api/v1/demo/),但随后触发了/error请求,这个请求没有携带JWT Token,被AnonymousAuthenticationFilter重置为匿名上下文,最终返回403。

1. 优先排查原接口异常

/error请求的触发,说明/api/v1/demo/接口在处理业务逻辑时抛出了未捕获的异常,导致Spring自动转发到默认错误端点。

  • 直接调试/api/v1/demo/接口代码,检查是否存在空指针、数据库操作失败等未处理异常。
  • 添加全局异常处理器(@RestControllerAdvice)捕获接口异常,避免触发默认错误转发。

2. 临时规避错误端点认证问题

如果暂时不需要调试异常,可以先给错误端点添加放行规则,避免返回403:

// 在SecurityConfig的authorizeHttpRequests中添加
.requestMatchers("/error").permitAll()

3. 验证JWT权限与AuthenticationProvider

  • 确认userDetails.getAuthorities()是否返回非空的权限集合,即使配置只要求authenticated(),空权限集合也可能导致认证逻辑异常。
  • 检查自定义AuthenticationProvider的实现,确认其authenticate方法不会覆盖或清除已设置的SecurityContext认证信息。

4. 确认JWT有效性验证逻辑

调试jwtService.isTokenValid方法,确认是否正确验证了Token的签名、过期时间等核心参数,避免因Token验证不通过导致认证未生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:55:56