密码找回接口已放行仍遇JWT过期错误,如何分离JWT认证?
解决JWT过期错误,实现密码找回与JWT认证分离
问题根源:你配置的jwtAuthFilter会拦截所有请求(包括已设置permitAll的/user/**路径),当请求携带过期JWT时,过滤器会触发校验并抛出过期错误——permitAll只是授权环节放行,过滤器的执行优先级在授权之前,所以会先触发JWT校验逻辑。
解决方案:修改JwtAuthFilter,跳过无需认证的路径
让JWT过滤器在处理请求前判断路径,若属于放行列表则直接跳过校验,具体实现如下:
假设你的JwtAuthFilter继承自OncePerRequestFilter,修改其doFilterInternal方法:
@Component public class JwtAuthFilter extends OncePerRequestFilter { // 注入你的JwtService、UserDetailsService等依赖 private final JwtService jwtService; private final UserDetailsService userDetailsService; // 定义无需JWT认证的路径,和SecurityFilterChain中的配置保持一致 private final List<String> allowedPaths = Arrays.asList("/api/v1/auth/**", "/user/**"); public JwtAuthFilter(JwtService jwtService, UserDetailsService userDetailsService) { this.jwtService = jwtService; this.userDetailsService = userDetailsService; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestPath = request.getRequestURI(); // 检查当前请求是否属于放行路径,是则直接放行 boolean isPathAllowed = allowedPaths.stream().anyMatch(path -> AntPathMatcher.DEFAULT_PATH_MATCHER.match(path, requestPath) ); if (isPathAllowed) { filterChain.doFilter(request, response); return; } // 以下是原有的JWT校验逻辑,仅对需要认证的路径执行 String authHeader = request.getHeader("Authorization"); String token = null; String username = null; if (authHeader != null && authHeader.startsWith("Bearer ")) { token = authHeader.substring(7); username = jwtService.extractUsername(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); } }
额外说明
- 测试时如果请求头携带了过期JWT,即使是密码找回接口,之前的过滤器仍会触发校验;修改过滤器后,会直接跳过这些路径的校验,不再抛出JWT过期错误。
- 确保
allowedPaths中的路径和SecurityFilterChain里permitAll的路径完全一致,使用AntPathMatcher来匹配ant风格的路径(和Spring Security的requestMatchers规则一致)。
内容的提问来源于stack exchange,提问作者Timoumi
相关产品推荐
相关产品推荐

