我主要使用 Nextjs 作为我的前端,使用 Java springboot 作为我的后端。不过,我想使用 nextjs 中间件通过 JWT 保护我的路由。由于 jsonwebtoken 无法在边缘函数上运行,我正在使用 jose。
尝试从 cookie 中获取 JWT 后,我尝试验证它并收到此消息:
JWSSignatureVerificationFailed:签名验证失败
这是我的令牌在 Spring 后端的签名:
public static String generateJwtToken(AppUser user) {
Map<String, Object> claims = new HashMap<>();
return Jwts.builder()
.setClaims(claims)
.setSubject(user.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + TOKEN_VALIDITY * 1000))
.signWith(SignatureAlgorithm.HS512, jwtSecret)
.compact();
}
这是在我的 nextjs 中间件文件中验证它的尝试:
const token = request.cookies.get('jwt');
const { payload } = await jwtVerify(
token,
new TextEncoder().encode(process.env.SECRET_KEY)
);
注意:jwtSecret 和 SECRET_KEY 是来自完全相同的 .env 文件的完全相同的值。任何帮助将不胜感激
在这里或多或少找到了我的答案https://github.com/auth0/node-jsonwebtoken/issues/208#issuecomment-231861138。这个确切的注释解释了秘密密钥应该发生什么。
至于我在代码中修复的内容,我必须以字节数组的形式返回密钥。
.signWith(SignatureAlgorithm.HS512, jwtSecret.getBytes("UTF-8"))
免责声明: 请务必了解将密钥作为字符串而不是字节数组发送的安全含义。
根据@juliomalves 的回复和他链接的 github 问题,我做了一些小小的改变。
我的后端响应是在 Cookie 标头中设置的,我不想解析它并将其作为字节发送到我的前端(因为我使用该 Cookie 来获取 jwt 令牌并在其他请求中将其发送回后端以进行授权).
因此,如果您想将密钥保留为字符串并将其编码在中间件中,您可以这样做:
const base64Key = Buffer.from(YOUR_STRING_SECRET_KEY,'base64'));
然后您可以像之前一样使用 jwtVerify 进行验证
const { payload } = await jwtVerify(
token,
base64key
);