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

无JWT签名密钥时,如何基于JWT角色实现Spring Security授权?

解决方案:无签名密钥下解码JWT并实现Spring Security权限控制

一、问题根源

你当前使用的parseClaimsJws()方法会强制验证JWT签名,没有密钥时会抛出异常(被你捕获后未处理),导致claims始终为空。要跳过签名验证,需使用JJWT专门的无校验解析方式。

二、正确的JJWT解码代码(不验证签名)

适配JJWT 0.11.x及以上版本

该版本提供了官方的无签名验证模式:

String token = "ey.....";
Claims claims;
try {
    claims = Jwts.parser()
            .unsecured() // 启用无签名校验模式,允许解析跳过签名验证的JWT
            .parseSignedClaims(token)
            .getPayload();
} catch (Exception e) {
    e.printStackTrace(); // 不要吞异常,方便排查问题
}

适配JJWT 0.9.x及更低版本

旧版本需手动设置空密钥并处理签名异常:

String token = "ey.....";
Claims claims;
try {
    claims = Jwts.parser()
            .setSigningKey(null) // 设置空密钥
            .parseClaimsJws(token)
            .getBody();
} catch (SignatureException e) {
    // 捕获签名验证失败异常,改用无签名解析方式
    claims = Jwts.parser()
            .parseClaimsJwt(token)
            .getBody();
} catch (Exception e) {
    e.printStackTrace();
}

三、Spring Security集成步骤

1. 自定义JWT认证过滤器

在请求链路中提取JWT、解码并注入权限信息:

public class JwtAuthorizationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = extractTokenFromRequest(request);
        if (token != null) {
            Claims claims = decodeJwt(token);
            if (claims != null) {
                String username = claims.getSubject();
                List<String> roles = claims.get("roles", List.class);
                
                // 转换为Spring Security识别的权限格式
                Collection<? extends GrantedAuthority> authorities = roles.stream()
                        .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
                        .collect(Collectors.toList());
                
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        username, null, authorities);
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }
        filterChain.doFilter(request, response);
    }
    
    // 从请求头提取JWT令牌
    private String extractTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
    
    // 调用前面的JWT解码逻辑
    private Claims decodeJwt(String token) {
        try {
            return Jwts.parser()
                    .unsecured()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

2. 配置Spring Security规则

注册过滤器并定义API权限:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(csrf -> csrf.disable()) // 关闭CSRF(适配REST API场景)
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/api/admin/**").hasRole("ADMIN") // 管理员专属接口
                        .requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN") // 用户/管理员可访问
                        .anyRequest().authenticated() // 其他接口需认证
                )
                .addFilterBefore(new JwtAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
        
        return http.build();
    }
}

四、关键注意事项

  • 安全风险:跳过签名验证意味着任何伪造的JWT都能通过授权,仅适合内部测试或完全信任的封闭环境,生产环境必须验证签名。
  • 版本依赖:确保项目引入正确的JJWT版本,0.11.x版本的Maven依赖如下:
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-core</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

内容的提问来源于stack exchange,提问作者noob555

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:25:34