Spring Security JWT场景下hasRole()读取角色及Actuator授权403问题
Spring Security JWT角色校验403问题解决方案
核心原理说明
Spring Security的hasRole()方法默认会给传入的角色名自动拼接ROLE_前缀,再从SecurityContextHolder中存储的Authentication对象的authorities(权限集合)属性中匹配对应值,匹配成功才会放行。
现有代码的问题点
你代码里有两个核心缺失导致403:
- 你在
JwtTokenVerifier过滤器中构造UsernamePasswordAuthenticationToken时,第三个参数(权限集合)传入了null,等于完全没有把JWT里存储的角色信息同步给Spring Security的上下文,校验时自然找不到对应角色。 - 你没有在JWT校验通过后,从Claims中读取你提前存入的
Roles字段转成Spring要求的权限对象。
修改方案
只需要修改JwtTokenVerifier中JWT校验通过后的逻辑,把角色信息读取并注入到权限集合中即可,修改后代码如下:
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION); if (authorizationHeader == null || authorizationHeader.isEmpty() || !authorizationHeader.startsWith(jwtConfig.getTokenPrefix())) { String requestParam = request.getParameter("token"); if (requestParam != null && !requestParam.isEmpty() && requestParam.startsWith(jwtConfig.getTokenPrefix())) { authorizationHeader = requestParam; } else { filterChain.doFilter(request, response); return; } } try { if (jwtConfig.validateJwtToken(authorizationHeader)) { String username = jwtConfig.getUserNameFromJwtToken(authorizationHeader); // 新增代码:从JWT中读取角色列表转成权限集合 String token = authorizationHeader.replace(jwtConfig.getTokenPrefix(), ""); Claims claims = Jwts.parserBuilder() .setSigningKey(Keys.hmacShaKeyFor(jwtConfig.getSecretKey().getBytes())) .build() .parseClaimsJws(token) .getBody(); List<String> roles = claims.get("Roles", List.class); List<GrantedAuthority> authorities = roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); // 把权限集合传给Authentication构造方法 Authentication auth = new UsernamePasswordAuthenticationToken( username, new WebAuthenticationDetailsSource().buildDetails(request), authorities ); SecurityContextHolder.getContext().setAuthentication(auth); } } catch (Exception e) { e.printStackTrace(); response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); } filterChain.doFilter(request, response); }
校验注意事项
你生成JWT时存入的角色已经是ROLE_ACTUATOR,符合Spring Security默认的前缀要求,所以antMatchers("/actuator/**").hasRole("ACTUATOR")的配置无需修改,修复后即可正常校验通过。
内容的提问来源于stack exchange,提问作者Programmer
相关产品推荐
相关产品推荐

