Java Spring JWT生成认证令牌仍遇401未授权错误求助
结合你提供的代码,以下是针对性的排查和修复方向:
1. 调整过滤器执行顺序
Spring Security的过滤器链顺序直接决定认证逻辑是否生效。你当前用addFilter()添加JwtAuthorizationFilter,该方法会将过滤器放到默认位置,可能晚于授权拦截逻辑执行——也就是说Spring验证权限时,SecurityContext里还没你设置的认证信息,直接返回401。
修复方式:把JwtAuthorizationFilter放到自定义认证过滤器之前,确保JWT解析先执行:
// 替换原addFilter语句 .addFilterBefore(new JwtAuthorizationFilter(authenticationManager(authenticationConfiguration), userDetailsManager(), secret), JsonObjectAuthenticationFilter.class)
2. 修正认证令牌的创建逻辑
你创建UsernamePasswordAuthenticationToken时,用userDetails.getUsername()作为Principal,不符合Spring Security规范。正确做法是传入userDetails对象本身,这样Spring才能正确校验用户状态(启用/过期等):
// 原代码 UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), null, userDetails.getAuthorities()); // 修改为 UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
3. 修复请求路径匹配规则
你的管理员路径匹配规则缺少开头斜杠,会导致Spring无法正确匹配/admin/xxx这类请求,触发授权拦截:
// 原代码 .requestMatchers(HttpMethod.PUT, "admin/**").authenticated(); // 修改为 .requestMatchers(HttpMethod.PUT, "/admin/**").authenticated();
4. 验证UserDetails权限加载是否正常
虽然能拿到正确用户名,但要确认userDetailsService.loadUserByUsername(userName)返回的对象中,getAuthorities()是否包含有效权限集合。空权限或权限配置错误也会导致401,可以在过滤器中加日志验证:
logger.info("当前用户权限:{}", userDetails.getAuthorities());
5. 检查SecurityContext上下文是否被清空
由于配置了SessionCreationPolicy.STATELESS,需确保设置的认证上下文不会被后续过滤器清空。在doFilterInternal末尾加日志验证:
logger.info("过滤器执行后SecurityContext:{}", SecurityContextHolder.getContext().getAuthentication());
如果后续执行时上下文为空,说明有其他过滤器修改了SecurityContext,需要排查过滤器链中的其他组件。
内容的提问来源于stack exchange,提问作者czarobest

