配置放行规则后Spring Security仍认证所有请求如何解决
问题根因
- 自定义
JwtAuthenticationFilter逻辑错误:在JWT为空/校验不通过的else分支里,直接写入401响应返回,没有放行到后续Spring Security的权限判断逻辑,哪怕你配置了/123允许匿名访问、/asfsadf忽略安全校验,所有请求都会被这个过滤器直接拦截返回未认证。 web.ignoring()配置的路径是跳过Spring Security的过滤器链,但你自定义的JWT过滤器被声明为Spring Bean,默认会被加入全局Servlet过滤器链,哪怕是web.ignoring的路径也会被这个过滤器处理,同样会被拦截。
修复方案
1. 修改JWT过滤器核心逻辑
过滤器只做合法JWT的身份信息注入,不直接拦截无JWT/非法JWT的请求,权限判断交给Spring Security本身的逻辑处理即可:
@Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { try { String jwt = getJwtFromRequest(httpServletRequest); // 仅处理携带了合法JWT的请求,向上下文注入身份信息 if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) { int userId = tokenProvider.getUserIdFromJWT(jwt); UserDetails userDetails = userService.loadUserById(userId); if(userDetails != null) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest)); SecurityContextHolder.getContext().setAuthentication(authentication); } } // 移除原else分支的直接返回逻辑,所有情况都放行到后续过滤器 filterChain.doFilter(httpServletRequest, httpServletResponse); } catch (Exception ex) { // 异常场景清理上下文后放行,不要直接返回错误 SecurityContextHolder.clearContext(); filterChain.doFilter(httpServletRequest, httpServletResponse); } }
2. 配置过滤器跳过放行路径(可选优化)
如果要让web.ignoring()的路径完全不经过JWT过滤器的处理,可以重写过滤器的跳过判断方法:
@Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { // 这里配置所有需要跳过校验的路径即可 List<String> ignorePaths = Arrays.asList("/asfsadf", "/123"); String requestUri = request.getRequestURI(); return ignorePaths.stream().anyMatch(requestUri::equals); }
修改完成后,你原本配置的放行规则就会正常生效:无JWT的请求访问/123、/asfsadf可以正常通过,访问其他路径才会触发认证校验。
内容的提问来源于stack exchange,提问作者Trọng Nghĩa Lê Đình
相关产品推荐
相关产品推荐

