调用注册API端点遇403错误,触发MalformedJwtException异常
问题分析
你遇到的403错误和MalformedJwtException是因为JWT过滤器在权限校验前就执行了。虽然你在WebSecurityConfig里配置了POST /users允许匿名访问,但你添加的JWTFilter会拦截所有请求,包括白名单内的请求。当注册请求没有携带JWT时,过滤器尝试解析空的JWT字符串,就会抛出"JWT strings must contain exactly 2 period characters"的异常,最终导致返回403。
解决方法
核心思路是让JWTFilter跳过白名单中的请求(比如注册、登录接口),不对这些请求做JWT解析校验。
步骤1:修改JWTFilter逻辑
在你的JWTFilter类的doFilterInternal方法中,先判断当前请求是否属于白名单路径,如果是则直接放行,不执行JWT解析逻辑:
public class JWTFilter extends OncePerRequestFilter { // 定义需要跳过JWT校验的白名单路径和方法 private static final List<String> WHITELIST_PATHS = Arrays.asList( "/login", "/users" ); private static final List<HttpMethod> WHITELIST_METHODS = Arrays.asList( HttpMethod.POST ); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestPath = request.getRequestURI(); HttpMethod requestMethod = HttpMethod.valueOf(request.getMethod()); // 检查是否是白名单请求,直接放行 if (WHITELIST_PATHS.contains(requestPath) && WHITELIST_METHODS.contains(requestMethod)) { filterChain.doFilter(request, response); return; } // 原有JWT解析校验逻辑 String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { String token = authHeader.substring(7); try { // 解析JWT并设置认证信息到SecurityContext Claims claims = Jwts.parser() .setSigningKey("你的密钥") // 替换成实际使用的密钥 .parseClaimsJws(token) .getBody(); // ... 后续用户认证逻辑 } catch (MalformedJwtException e) { // 捕获异常并返回401,避免异常扩散导致请求中断 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "无效的JWT令牌"); return; } } filterChain.doFilter(request, response); } }
步骤2:确认WebSecurityConfig配置有效性
当前WebSecurityConfig中已经正确配置了POST /users的放行规则,无需修改,但要保证过滤器的白名单和这里的配置一致,避免出现路径或方法不匹配的情况。
额外注意事项
- JWT密钥建议通过
@Value从配置文件注入,不要硬编码在代码中。 - 对JWT解析异常要做针对性处理,返回明确的HTTP状态码(比如401),避免异常直接抛出影响请求流程。
内容的提问来源于stack exchange,提问作者JamesB
相关产品推荐
相关产品推荐

