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
相关产品推荐
相关产品推荐

