跳到主要内容
ecdsa.com
JJWT (Java)Java

错误信息

JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

也可能输出为

  • io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

JJWT (Java) — io.jsonwebtoken.security.SignatureException from JwtParser.parseSignedClaims

含义

JJWT 用你配置的密钥,对令牌的头部和载荷重新计算(HMAC)或验证(RSA、ECDSA、EdDSA)签名,结果与令牌的签名段不符。令牌解析正常,算法也与密钥相符;只是密钥和令牌并不配套,或者令牌在签名后被改动过。

原因

修复方法

  1. 1.

    用密钥定位器按 kid 查找密钥

    JJWT 0.12+ 支持 `keyLocator`:它接收头部,返回对应的密钥。再配合一个在密钥轮换时刷新的 JWKS。

    java
    import io.jsonwebtoken.*;
    import java.security.Key;
    
    // Pick the verification key by the token's kid instead of a single static key.
    Locator<Key> keys = new LocatorAdapter<>() {
      @Override
      protected Key locate(JwsHeader header) {
        Key key = publicKeysByKid.get(header.getKeyId()); // refreshed from the issuer's JWKS
        if (key == null) throw new UnsupportedJwtException("unknown kid " + header.getKeyId());
        return key;
      }
    };
    Jws<Claims> jws = Jwts.parser().keyLocator(keys).requireIssuer("https://issuer.example.com/").build().parseSignedClaims(token);
  2. 2.

    统一 HMAC 密钥的字节

    确定配置中的密钥是文本还是 base64,并让每一方都以相同的方式得出密钥。HMAC 计算器会显示两种解读方式下的 MAC。

    java
    // Both sides must derive the same key bytes. If the secret is stored base64-encoded, decode it.
    javax.crypto.SecretKey key = io.jsonwebtoken.security.Keys.hmacShaKeyFor(
        java.util.Base64.getDecoder().decode(System.getenv("JWT_SECRET_B64")));

相关错误

浏览完整的签名错误库