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

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())和CorsFilter Bean,这可能导致CORS配置冲突,建议保留其中一种方式:要么去掉CorsFilter Bean,在http.cors()中自定义配置;要么移除http.cors(Customizer.withDefaults()),使用自定义的CorsFilter。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:11:11