我正在使用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();
}
虽然可以成功解码令牌。每当我从jwt.io调试器验证它的签名时,它总是会导致无效的签名。可以看到here。
答案 0 :(得分:2)
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);
此外,为什么不考虑jwt.io
可能会被打破?它不是权威的jwt工具。
最后,我要注意你绝不应该使用明文字符串或随机字符串作为签名密钥。数字签名总是使用字节数组计算。如果您希望加密安全,则应始终使用足够长的安全随机字节数组来处理您正在使用的签名算法。
查看JJWT的Keys.secretKeyFor
方法,以生成足够长且足够强的密钥。
jwt.io
网站具有误导性,因为它不会使这一点变得明显,并暗示您可以使用任何旧字符串作为签名密钥。虽然它可以技术,但你绝对不应该这样做。如果需要将它们表示为字符串,则应始终使用随后为Base64编码的安全随机字节数组。这就是JJWT接受String作为键的方法假设它是Base64编码的原因 - 因为如果不是,那么你可能使用了无效或格式不正确的密钥。