已认证用户访问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
相关产品推荐
相关产品推荐

