【发布时间】:2019-07-20 01:35:12
【问题描述】:
当用户单击注销按钮时,如何使 JWT 令牌无效?我做了一些研究,但我找不到任何好的实现。
【问题讨论】:
标签: rest spring-boot jwt
当用户单击注销按钮时,如何使 JWT 令牌无效?我做了一些研究,但我找不到任何好的实现。
【问题讨论】:
标签: rest spring-boot jwt
您无法找到任何“过期”JWT 的方法,因为没有这种方法。可以说是JWT的缺点。
如果token 被泄露,那么这是一个大问题。如果您需要使令牌/会话无效,您可能需要考虑其他身份验证机制。
“无效”此类令牌的唯一方法是在后端使用其他 secret 密钥 - 这显然是一个非常可怕的想法!
但是,如果您正在寻找一种在前端“注销”用户的方法,只需从存储中清除 JWT。 (不过,如果该用户复制了令牌,他将能够针对 rest api 执行请求)。
【讨论】:
一种选择是只拥有一个bannedUsers 表。您甚至可以缓存此表。如果用户帐户遭到入侵,您可以将他们添加到表中,直到他们的令牌过期。每次都会查找(除非已缓存),但表上很可能总是有 0 条记录,因此速度会非常快。
【讨论】:
在与@RonOhRob 相同的行中,我建议使用jti (JWT ID) 声明。此声明为 JWT 提供了唯一标识符。
您的 JWT 有效负载如下所示:
{
"iss": "example.com",
"iat": "1300819080",
"exp": "1300819380",
"jti": "123e4567-e89b-42d3-a456-556642440000",
"username": "mneri"
}
当 JWT 手动过期时,您会将 jti 插入黑名单。该值应保留在表中,直到令牌自然到期。现在,对于每个请求,还应该检查表内是否有jti;如果发现访问被拒绝。
如果用户想要使他的所有令牌过期,还有另一个涉及iat (Issued At) 声明的简单策略:将deny_before 字段添加到user 表并注册expire_all API 调用的日期。和以前一样,您必须为每个请求添加检查。
有关如何将 JWT 集成到 Spring 中的完整参考,请查看 JavaBrain's video。
视频中的人正在使用jjwt,但我推荐auth0's java-jwt 库,根据我的口味,它提供了更好的界面:
JWT.create()
.withJWTId(UUID.randomUUID().toString())
.withIssuer(ISSUER)
.withIssuedAt(issueDate)
.withExpiresAt(expireDate)
.withClaim("username", user.getUsername())
.sign(Algorithm.HMAC256("secret"));
现在,在你的JWTFilter:
JWTVerifier verifier = JWT.require(ALGORITHM).withIssuer(ISSUER).build();
DecodedJWT decoded = verifier.verify(jwt);
if (blacklistService.find(jwt.getId())) {
throw new JWTVerificationException();
}
User user = userService.loadByUsername(jwt.getClaim("username").asString());
if (user.getDenyBefore() != null && user.getDenyBefore().compareTo(jwt.getIssuedAt()) > 0) {
throw new JWTValidationException();
}
【讨论】: