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

Spring Security放行请求被JwtAuthenticationFilter拦截问题求助

问题分析与解决方案

问题根源

你的JwtAuthenticationFilter作为自定义OncePerRequestFilter,执行优先级高于Spring Security的授权校验逻辑(FilterSecurityInterceptor)。当前过滤器仅硬编码放行/ss023/user/register,其余所有请求都会强制进入JWT校验流程并返回未授权,导致Security配置中permitAll()的其他路径完全失效。

解决方案:统一管理放行路径

修改JwtAuthenticationFilter,使用路径匹配器统一匹配所有无需认证的路径,和Security配置保持一致:

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtTokenService jwtTokenService;
    private final UserDetailsService userDetailsService;
    // 同步Security配置中的放行路径,支持通配符
    private static final List<String> PERMIT_ALL_PATHS = Arrays.asList(
            "/ss023/user/register",
            "/ss023/user/getStringTwo",
            "/css/**",
            "/register",
            "/login"
    );
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    // 补全构造方法
    public JwtAuthenticationFilter(JwtTokenService jwtTokenService, UserDetailsService userDetailsService) {
        this.jwtTokenService = jwtTokenService;
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {

        String path = request.getRequestURI();
        
        // 检查当前路径是否属于放行列表
        boolean isPermitted = PERMIT_ALL_PATHS.stream()
                .anyMatch(permitPath -> pathMatcher.match(permitPath, path));
        
        if (isPermitted) {
            // 直接放行,跳过JWT校验
            filterChain.doFilter(request, response);
            return;
        }

        // 原有JWT校验逻辑保持不变
        String authToken = jwtTokenService.getToken(request);

        if (null != authToken) {
            String username = jwtTokenService.getUsernameFromToken(authToken);
            if (null != username) {
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                if (jwtTokenService.validateToken(authToken, userDetails)) {
                    Authentication authentication = new UsernamePasswordAuthenticationToken(
                            userDetails,
                            null,
                            userDetails.getAuthorities()
                    );
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                    filterChain.doFilter(request, response);
                } else {
                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    response.setContentType("application/json");
                    response.getWriter().write("{\"error\":\"Bearer Token Expired\"}");
                }
            } else {
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                response.setContentType("application/json");
                response.getWriter().write("{\"error\":\"Wrong bearer token\"}");
            }
        } else {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json");
            response.getWriter().write("{\"error\":\"No bearer token\"}");
        }
    }
}

关键注意事项

  1. 使用AntPathMatcher支持通配符路径(如/css/**),避免直接用equals导致通配符失效;
  2. 必须放行/login路径,否则自定义登录过滤器CustomUsernamePasswordAuthenticationFilter无法处理登录请求;
  3. 放行路径需和Security配置中的requestMatchers保持同步,避免出现配置不一致的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 13:07:51