我正在尝试使用 JWT 令牌实现我自己的身份验证。我在 Java Spring boot 中生成 jwt 令牌。
我使用这个网站生成一个base64编码的字符串,用作jwt秘密:https://www.devglan.com/online-tools/hmac-sha256-online?ref=blog.tericcabrel.com
这是相关的 Spring boot 代码:
private Key getSignInKey() {
byte[] keyBytes = Decoders.BASE64.decode(secretKey);
return Keys.hmacShaKeyFor(keyBytes);
}
Jwts
.builder()
.setClaims(extraClaims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(getSignInKey(), SignatureAlgorithm.HS256)
.compact();
效果很好,问题不在这里。问题出现在 nextjs 端,我在登录后尝试验证从 api 检索到的 jwt 令牌:
export async function verifyAuth() {
const token = cookies().get('user-token')
if (!token) {
return null
}
const jwtSecretKey = getJwtSecretKey()
const { payload } = await jwtVerify(token.value, new TextEncoder().encode(jwtSecretKey))
return payload as JwtPayload
}
这不断抛出以下异常,尽管我使用上面网站生成的相同密钥(getJwtSecretKey 只是从 .env 返回 env 变量,而我使用 jose):
digest: "3414803446"
⨯ JWSSignatureVerificationFailed: signature verification failed
at async verifyAuth (./lib/auth.ts:74:25)
at async Home (./app/page.tsx:11:18)
我在这里做错了什么?
签名过程中传递的秘密在用作签名秘密之前从 Base64 字符串中解码。在将秘密传递给
jose
之前,您必须执行相同的操作,否则 new TextEncoder().encode(jwtSecretKey)
仅使用编码字节作为秘密。
这个
const secret = Buffer.from(jwtSecretKey, 'base64')
相当于
keyBytes = Decoders.BASE64.decode(secretKey);