JJWT 生成的令牌具有无效签名

Kye*_*JmD 4 java jwt json-web-token jjwt

我正在使用 JJWT 库生成 JWT 令牌。我按如下方式生成令牌。我使用虚拟值作为我的密钥。

我们可以假设jwt.security.key=security-key

   @Value("${jwt.security.key}")
    private String key;

    @Value("${ws.issuer}")
    private String issuer;

    static final long ONE_MINUTE_IN_MILLIS=60000;

    static final long TOKEN_DURATION_IN_MIN=30L;

    private SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

    @Override
    public String issueToken(String userName) {

        long nowMillis = System.currentTimeMillis();
        long expMillis = nowMillis + (ONE_MINUTE_IN_MILLIS * TOKEN_DURATION_IN_MIN);

        return  Jwts
                .builder()
                .setId("01")
                .setIssuedAt(new Date(nowMillis))
                .setHeaderParam("typ","JWT")
                .setSubject(userName)
                .setIssuer(issuer)
                .setExpiration(new Date(expMillis))
                .signWith(signatureAlgorithm, key).compact();

    }
Run Code Online (Sandbox Code Playgroud)

虽然token可以成功解码。每次我验证 jwt.io 调试器的签名时,总是会导致签名无效。可以在这里看到。

Les*_*ood 5

security-key不是有效的 Base64 编码字符串。阅读 JavaDoc 和signWith(SignatureAlgorithm, String)方法的参数名称:

/**
 * Signs the constructed JWT using the specified algorithm with the specified key, producing a JWS.
 * 
 * <p>This is a convenience method: the string argument is first BASE64-decoded to a byte array and this resulting
 * byte array is used to invoke {@link #signWith(SignatureAlgorithm, byte[])}.</p>
 *
 * @param alg                    the JWS algorithm to use to digitally sign the JWT, thereby producing a JWS.
 * @param base64EncodedSecretKey the BASE64-encoded algorithm-specific signing key to use to digitally sign the
 *                               JWT.
 * @return the builder for method chaining.
 */
JwtBuilder signWith(SignatureAlgorithm alg, String base64EncodedSecretKey);
Run Code Online (Sandbox Code Playgroud)

此外,为什么不考虑它jwt.io可能会被破坏呢?它不是一个权威的jwt工具。

最后,我要指出的是,您永远不应该使用纯文本字符串或随机字符串作为签名密钥。数字签名始终使用字节数组计算。如果您希望加密技术安全,则应始终为您正在使用的签名算法使用足够长度的安全随机字节数组。

看一下 JJWTKeys.secretKeyFor生成足够长且足够强的密钥的方法。

jwt.io网站具有误导性,因为它没有使这一点显而易见,并且暗示您可以使用任何旧字符串作为签名密钥。虽然这在技术上是可行的,但你绝对不应该这样做。如果需要将它们表示为字符串,则应始终使用经过 Base64 编码的安全随机字节数组。这就是为什么接受 String 作为密钥的 JJWT 方法假定它是 Base64 编码的 - 因为如果不是,则您可能使用了无效或格式错误的密钥。