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

Spring Security 实现JWT令牌刷新后登录失败,报JWT签名不匹配错误

Spring Security 实现JWT令牌刷新后登录失败,报JWT签名不匹配错误

兄弟,我太懂这种排查半天找不到问题的头疼了!你这个报错的根源其实就在你的JwtUtils类里的key()方法上,咱们一步步拆解问题:

核心问题:每次生成/验证JWT时使用的密钥不一致

你当前的key()方法实现是这样的:

private Key key() {
    return Keys.secretKeyFor(SignatureAlgorithm.HS512);
}

这个方法每次调用都会生成一个全新的随机HS512密钥!这就导致:

  • 生成登录JWT时,用的是随机密钥A
  • 验证JWT时,又生成了另一个随机密钥B
    两个密钥完全不同,自然会触发JWT signature does not match locally computed signature的错误。更关键的是,你配置文件里的jwtSecret根本没被用到,完全浪费了!

修复方案

1. 修改key()方法,使用配置的jwtSecret生成固定密钥

把key()方法改成从配置的jwtSecret生成密钥,注意HS512算法要求密钥长度至少为512位(也就是64个字符),如果你的jwtSecret长度不够,记得先调整配置文件里的内容:

import java.nio.charset.StandardCharsets;

// ... 其他代码保持不变

private Key key() {
    return Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8));
}

2. 修复JWT生成时的Subject缺失问题

另外发现你的generateJwtToken方法没有设置Subject,但getUserNameFromJwtToken和getEmailFromJwtToken却尝试从Subject获取信息,这会导致后续获取用户信息失败,顺手一起修复:

public String generateJwtToken(Authentication authentication) {
    UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();

    return Jwts.builder()
            .setId("" + userPrincipal.getId())
            .setSubject(userPrincipal.getUsername()) // 新增:设置Subject为用户名/邮箱
            .setIssuedAt(new Date())
            .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
            .signWith(key(), SignatureAlgorithm.HS512)
            .compact();
}

为什么这样改就解决问题?

修改后,生成JWT和验证JWT时使用的是同一个基于配置jwtSecret生成的固定密钥,签名自然能匹配上,报错也就消失了。同时修复Subject的问题,能保证后续从JWT中正确提取用户信息。

备注:内容来源于stack exchange,提问作者Osmankaapa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 12:59:32