我想知道在更改密码/注销时使JWT无效而不点击db的最佳实践。
我有下面的想法,通过命中用户数据库来处理上述两种情况。
1.在密码更改的情况下,我检查存储在用户db中的密码(散列)。
2.在注销的情况下,我将最后一次注销时间保存在用户db中,因此,通过比较令牌创建时间和注销时间,我可以使这种情况无效。
但这两种情况的代价是每次用户点击api时都会命中用户db。任何最佳实践都是值得赞赏的。
更新:我认为我们不能在不点击db的情况下使JWT无效。所以我想出了一个解决方案。我已经发布了我的答案,如果你有任何问题,欢迎你。
发布于 2015-03-02 14:46:47
未使用刷新令牌时的:
1.更改密码时:当用户更改其密码时,请注意用户数据库中的更改密码时间,因此当更改密码时间大于令牌创建时间时,令牌无效。因此,剩余的会话将很快被注销。
2.当用户注销时:当用户注销时,将令牌保存在一个单独的数据库中(比如: InvalidTokenDB,在令牌过期时从数据库中删除令牌)。因此,用户从相应的设备注销,他在其他设备中的会话不受干扰。
因此,在使JWT无效时,我遵循以下步骤:
与上述方法相关的
对于每个api请求,我需要遵循上面所有的步骤,这可能会影响performance.
使用刷新令牌时的:,访问令牌过期时间为1天,刷新令牌有效期为终生有效
1.更改密码时:当用户更改密码时,更改用户的刷新token。因此,剩余的会话将很快被注销。
2.当用户注销时:当用户注销时,将令牌保存在一个单独的数据库中(比如: InvalidTokenDB,当令牌过期时从数据库中删除令牌)。因此,用户从相应的设备注销,他在其他设备中的会话不受干扰。
因此,在使JWT无效时,我遵循以下步骤:
刷新刷新检查令牌是否有效如果有效,则检查InvalidTokenDB.
与上述方法相关的
注释:虽然Hanz建议了一种在Using Refesh Token in Token-based Authentication is secured?中保护刷新令牌的方法,但我无法理解他在说什么。任何帮助都是非常感谢的。
因此,如果任何人有很好的建议,欢迎您的意见。
更新:我添加了答案,以防你的应用程序不需要生命周期到期的刷新令牌。这个答案是由Sudhanshu (https://stackoverflow.com/users/4062630/sudhanshu-gaur)给出的。谢谢苏丹书。所以我相信这是最好的方法,
不需要刷新令牌且访问令牌未过期时的:
当用户登录时,在他的用户数据库中创建一个没有过期时间的登录令牌。
因此,在使JWT无效时,请执行以下步骤:
用户更改其密码,从其用户数据库中删除所有令牌,并要求他再次登录。
因此,使用这种方法,您既不需要在数据库中存储注销令牌,直到它们过期,也不需要在更改密码时存储令牌创建时间,这在上面的情况下是需要的。然而,我相信只有当你的应用程序有不需要刷新令牌并且令牌不过期的需求时,这种方法才有效。
如果有人对这种方法感兴趣,请让我知道。欢迎您的评论:)
发布于 2015-02-27 16:35:34
据我所知,在不以某种方式涉及数据库的情况下,无法任意使令牌无效。
如果您的服务可以在多个设备上访问,请小心使用方法2。考虑下面的场景...
您可能想了解一下refresh tokens的概念,尽管它们也需要数据库存储。
有关类似问题的讨论,也请参阅here,特别是IanB的解决方案,它可以节省一些数据库调用。
个人提出的解决方案,这就是我处理it...user身份验证的方法,颁发的访问令牌有效期短(例如15分钟),刷新令牌的有效期更长或无限期。将该刷新令牌记录存储在db中。
每当用户处于“活动”状态时,每次都会发出新的身份验证令牌(每次的有效期为15分钟)。如果用户超过15分钟未处于活动状态,然后发出请求(因此使用过期的jwt),请检查刷新令牌的有效性。如果它是有效的(包括数据库检查),则发出一个新的身份验证令牌。
如果用户在设备上或通过网站“注销”,则销毁客户端的两个访问刷新令牌,并重要地撤销所使用的刷新令牌的有效性。如果用户在任何设备上更改其密码,则在其访问令牌到期后立即撤销其所有刷新令牌,强制其重新登录。这确实留下了一个“不确定的窗口”,但如果不是每次都达到db,这是不可避免的。
使用这种方法还可以让用户在需要时“撤销”对特定设备的访问,就像许多主要的web应用程序一样。
发布于 2016-12-06 14:34:13
我看到必须命中db来验证或使每个api请求的令牌无效,然而,正如我在这里看到的那样,整个过程本可以更简单。
每当创建jwt时,即在登录或更改/重置密码期间,将带有userid的jwt插入到表中,并为每个jwt维护一个jti (基本上是一个uuid号)。jwt有效负载中也包含相同的jti。有效地,jti唯一地标识jwt。当从多个设备或浏览器访问帐户时,用户可以同时具有多个jwts,在这种情况下,jti区分设备或用户代理。
因此,表模式应该是jti | userId。(当然还有一个主键)
对于每个api,检查jti是否在表中,这意味着jwt是有效的。
创建一个具有新jti的新jwt并将其插入到表中。
当用户注销时,删除该用户的特定jti,但不是全部。将只有一次登录,而不是一次注销。因此,当用户注销时,他不应该从所有设备上注销。但是,删除所有jtis也会从所有设备注销。
因此,这将是一个表,没有日期比较。此外,如果使用或不使用刷新令牌,情况也是一样的。
然而,为了最小化db干扰和可能的延迟,高速缓存的使用肯定有助于缓解处理时间方面的问题。
注意:如果你投了反对票,请说明理由。
https://stackoverflow.com/questions/28759590
复制相似问题