Spring Security 6.x配置后仍拦截所有端点问题求助
问题分析
你的问题根源在于**JwtAuthenticationFilter会拦截所有请求**,包括你配置了permitAll()的/api/auth/**端点。由于OncePerRequestFilter的执行顺序在Spring Security的授权规则之前,当请求/api/auth/**时,Filter会先检查Authorization头,发现没有Bearer token就直接返回401,导致后续的授权规则(允许匿名访问)根本没有机会生效。
解决方案
修改JwtAuthenticationFilter,添加逻辑跳过不需要JWT验证的路径(比如/api/auth/**),让这些请求直接进入后续过滤链,触发授权规则的permitAll()。
修改后的JwtAuthenticationFilter代码
@Log4j2 @Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtService jwtService; private final UserDetailsService userDetailsService; private final ObjectMapper objectMapper; // 用于路径匹配的工具类 private final AntPathMatcher pathMatcher = new AntPathMatcher(); @Override protected void doFilterInternal( @NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain filterChain ) throws IOException { try { // 跳过不需要JWT验证的路径,直接放行 if (pathMatcher.match("/api/auth/**", request.getRequestURI())) { filterChain.doFilter(request, response); return; } final String authHeader = request.getHeader("Authorization"); if (authHeader == null || !authHeader.startsWith("Bearer ")) { String errorPayload = objectMapper.writeValueAsString(Map.of( "type", "about:blank", "title", "Bad Authorization", "status", HttpServletResponse.SC_UNAUTHORIZED, "detail", "The Authorization header should contain a Bearer token value." )); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/problem+json"); response.getWriter().write(errorPayload); return; } final String jwt = authHeader.substring(7); final String userEmail = jwtService.extractUsername(jwt); if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = userDetailsService.loadUserByUsername(userEmail); if (jwtService.isTokenValid(jwt, userDetails)) { var authToken = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities() ); authToken.setDetails( new WebAuthenticationDetailsSource().buildDetails(request) ); SecurityContextHolder.getContext().setAuthentication(authToken); } } filterChain.doFilter(request, response); } catch (Exception ex) { log.error(ex.getMessage(), ex); String errorPayload = objectMapper.writeValueAsString(Map.of( "type", "about:blank", "title", "SF1", "status", HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "detail", "An error occurred while processing the request." )); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setContentType("application/problem+json"); response.getWriter().write(errorPayload); } } }
额外说明
- 如果你有更多不需要JWT验证的路径,可以扩展路径匹配逻辑,比如用
pathMatcher.matchAny("/api/auth/**", "/public/**", "/actuator/**", request.getRequestURI())实现多路径跳过 - 你的Security配置中同时存在
cors(Customizer.withDefaults())和CorsFilterBean,这可能导致CORS配置冲突,建议保留其中一种方式:要么去掉CorsFilterBean,在http.cors()中自定义配置;要么移除http.cors(Customizer.withDefaults()),使用自定义的CorsFilter。
内容的提问来源于stack exchange,提问作者bezbos.
相关产品推荐
相关产品推荐

