Spring Boot配置401未授权问题:如何让注册接口绕过JwtConfigurer配置
解决Spring Security中JWT过滤器拦截公开注册接口的问题
这个问题的核心原因是:你的JwtTokenFilter会拦截所有请求(包括你设置了permitAll的/auth/register),并且在Spring Security的授权决策阶段之前执行。即使你在authorizeRequests里允许了该路径匿名访问,过滤器已经先一步校验JWT,没有token就返回401了。
要解决这个问题,你需要让JwtTokenFilter主动跳过这些公开路径,直接放行,不需要执行JWT校验逻辑。下面是具体的实现步骤:
步骤1:修改JwtTokenFilter,添加忽略路径逻辑
在过滤器中加入路径判断,如果请求路径属于公开路径,就直接跳过JWT校验:
import org.springframework.security.web.util.matcher.AntPathMatcher; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; public class JwtTokenFilter extends OncePerRequestFilter { private final JwtTokenProvider jwtTokenProvider; private final SecurityUtils securityUtils; private final List<String> ignoredPaths; private final AntPathMatcher pathMatcher = new AntPathMatcher(); // 构造方法新增忽略路径参数 public JwtTokenFilter(JwtTokenProvider jwtTokenProvider, SecurityUtils securityUtils, List<String> ignoredPaths) { this.jwtTokenProvider = jwtTokenProvider; this.securityUtils = securityUtils; this.ignoredPaths = ignoredPaths; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestPath = request.getRequestURI(); // 检查当前路径是否在忽略列表中,是则直接放行 for (String ignoredPath : ignoredPaths) { if (pathMatcher.match(ignoredPath, requestPath)) { filterChain.doFilter(request, response); return; } } // 原来的JWT校验逻辑,只对非公开路径执行 String token = jwtTokenProvider.resolveToken(request); if (token != null && jwtTokenProvider.validateToken(token)) { Authentication auth = jwtTokenProvider.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(auth); } filterChain.doFilter(request, response); } }
步骤2:更新JwtConfigurer,支持配置忽略路径
给配置类添加设置忽略路径的方法,方便在configure中传入公开路径:
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.SecurityConfigurerAdapter; import org.springframework.security.web.DefaultSecurityFilterChain; import java.util.ArrayList; import java.util.List; public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { private final JwtTokenProvider jwtTokenProvider; private final SecurityUtils securityUtils; private List<String> ignoredPaths = new ArrayList<>(); public JwtConfigurer(JwtTokenProvider jwtTokenProvider, SecurityUtils securityUtils) { this.jwtTokenProvider = jwtTokenProvider; this.securityUtils = securityUtils; } // 提供链式调用的方法设置忽略路径 public JwtConfigurer ignorePaths(List<String> paths) { this.ignoredPaths = paths; return this; } @Override public void configure(HttpSecurity http) { // 创建过滤器时传入忽略路径 JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider, securityUtils, ignoredPaths); http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); } }
步骤3:在configure方法中配置公开路径
把需要跳过JWT校验的路径同时传给authorizeRequests和JwtConfigurer,保持配置一致:
import java.util.Arrays; import java.util.List; @Override protected void configure(HttpSecurity http) throws Exception { // 定义所有公开路径 List<String> publicPaths = Arrays.asList("/auth/register", "/auth/signin"); http .cors() .and() .httpBasic().disable() .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers(publicPaths.toArray(new String[0])).permitAll() .anyRequest().authenticated() .and() // 给JwtConfigurer传入忽略路径 .apply(new JwtConfigurer(jwtTokenProvider, securityUtils).ignorePaths(publicPaths)); }
这样修改后,当请求/auth/register时,JwtTokenFilter会直接放行,不会执行JWT校验,然后进入授权阶段,permitAll规则生效,就能正常访问注册接口了。
内容的提问来源于stack exchange,提问作者Matthew Kulich
相关产品推荐
相关产品推荐

