You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:15:06