我想在下一个项目中实现JWT。我只是想知道是否有任何最好的方法来实现JWT中所有设备的注销。由于JWT是无状态机制,我们是否必须涉及redis / db?
答案 0 :(得分:3)
我发现以下是用jwt处理一些事情的最佳方法。
由于jwt是无状态机制,我遇到了以下问题。
如何实施退出?当有人试图注销时,因为它是无状态的,所以会出现使令牌无效的问题。
<强>解决方案:强> 使用redis作为处理所有令牌的内存数据库,每次用户登录时保存令牌(与令牌具有相同的ttl),与每个请求交叉检查以及令牌验证。当有人想要注销时,从redis和客户端删除令牌。由于我们在redis中进行交叉检查,当用户注销并尝试使用相同令牌系统访问时,将无法在redis中找到令牌,因此请处理并抛出 未经身份验证的错误。
当用户更改密码时,如何无效同一用户的所有令牌?
如何实施从所有设备退出功能?
解决方案:由于我们在redis中存储令牌,我们必须搜索与给定用户相关的所有令牌,并在用户登录时从redis中删除它们或在数据库中存储令牌,找出所有与用户相关的令牌,获取令牌ID并从redis中删除它们。在db中存储更好,因为dbs更适合查找操作。
答案 1 :(得分:1)
我们可以在创建新用户时在数据库中保存随机JWT机密吗?如果我们要注销所有设备,只需生成新的Secret,所以所有OLD令牌现在都无效。对于正常注销,只需删除前端中的令牌
答案 2 :(得分:0)
(1) 如果所有生成的令牌都存储在后端,那么清除存储就很简单,如果令牌已映射到用户,您只需清除特定用户的令牌.
(2) 您可以添加一个日期字段,例如“invalidate_before”以及 user,该字段应在更改密码时更新,退出所有设备等。 只需在此类事件上将 invalidate_before 更新为 currentTime()。 每次创建新令牌时,在令牌负载中添加创建时间, 要验证传入请求中的令牌,只需检查有效负载中的创建时间是否大于该用户在 db 中的 invalidate_before 时间
(3) 当你创建一个新用户时,只为那个用户创建一个秘密,然后你可以用那个特定的秘密签署每个用户令牌,就像 (2) 更改密码、从所有设备注销等事件,应该创建一个新的秘密。 这样你也可以通过检查签名来使无效。
(2) 和 (3) 的开销是,验证将是一个 2 步过程,它涉及数据库读取
-已发布相同的 here