在更改密码和注销node.js时使JWT无效的最佳实践?

我想知道的最佳实践,无需更改密码/注销时db分配JWT无效。

我有下面的想法通过点击用户数据库来处理上述2个案例。

1.密码更改的情况下,我检查存储在用户数据库中的密码(散列)。

2.退出login时,我将最后退出时间保存在用户数据库中,因此通过比较令牌创build时间和退出时间,我可以使这种情况失效。

但是,这两种情况是以每次用户点击api时触及用户db为代价的。 任何最佳实践表示赞赏。

更新:我不认为我们可以使JWT无效,而不击中分贝。 所以我想出了一个解决scheme。 我已经发布了我的答案,如果您有任何疑虑,欢迎您。

当不使用刷新令牌时:

1.更改密码:当用户更改密码时,请记下用户db中的更改密码时间,所以当更改密码时间大于令牌创build时间时,令牌无效。 因此剩下的会话很快就会被注销。

2.用户注销时:当用户注销时,将令牌保存在一个单独的数据库中(比如:InvalidTokenDB,当令牌到期时从Db中删除令牌)。 因此,用户从相应设备注销,其他设备中的会话不受干扰。

因此,虽然使智威汤逊无效,我遵循以下步骤:

  1. 检查令牌是否有效。
  2. 如果有效,请检查它是否存在于invalidTokenDB(一个数据库,注销的令牌将被存储直到其到期时间)。
  3. 如果不存在,则检查创build的令牌时间并更改用户数据库中的密码时间。
  4. 如果更改密码时间<令牌创build时间,则令牌有效。

关注上述方法

  1. 对于每个API请求,我需要按照上面的所有步骤进行操作,这可能会影响性能。

使用刷新令牌时:访问令牌期限为1天,刷新令牌为有效期限

1.更改密码时:当用户更改密码时,更改用户的刷新标记。 因此剩下的会话很快就会被注销。

2.用户注销时 :用户注销时,将令牌保存在单独的数据库(例如:InvalidTokenDB,当令牌到期时从令牌中删除令牌)。 因此,用户从相应设备注销,其他设备中的会话不受干扰。

因此,虽然使智威汤逊无效,我遵循以下步骤:

  1. 检查令牌是否有效
  2. 如果有效,请检查令牌是否存在于InvalidTokenDB中。
  3. 如果不存在,请使用userDB中的刷新标记检查刷新标记。
  4. 如果等于,那么它是一个有效的标记

关注上述方法

  1. 对于每个API请求,我需要按照上面的所有步骤进行操作,这可能会影响性能。
  2. 如何使刷新令牌无效,因为刷新令牌没有有效性,如果黑客使用它,仍然authentication是有效的,请求将始终成功。

注意 :尽pipeHanz提出了一种在基于令牌的身份validation中使用Refesh令牌来确保刷新令牌安全的方法? ,我无法理解他在说什么。 任何帮助表示赞赏。

所以如果有人有很好的build议,欢迎您的评论。

更新:我添加了答案,因为您的应用程序不需要使用生命周期刷新令牌。 这个答案是由Sudhanshuhttps://stackoverflow.com/users/4062630/sudhanshu-gaur )给出的。 谢谢Sudhanshu。 所以我相信这是做到这一点的最好方法,

当不需要刷新令牌并且不存在访问令牌时:

当用户login时,在他的用户数据库中创build一个没有到期时间的login令牌。

因此,在使JWT无效的同时,按照以下步骤操作,

  1. 检索用户信息并检查令牌是否在他的用户数据库中。 如果允许的话。
  2. 当用户注销时,只从他的用户数据库中删除这个令牌。
  3. 当用户更改他的密码时,从他的用户数据库中删除所有的令牌,并要求他再次login。

因此,使用这种方法,您不需要将注销令牌存储在数据库中,直到它们到期,也不需要在更改以上情况下所需的密码的同时存储令牌创build时间。 不过,我相信这种方法只适用于你的应用程序有需求,没有刷新令牌需要和没有到期的令牌。

如果有人关心这个方法,请告诉我。 您的意见是欢迎:)

我无法以任何方式随意地使一个令牌失效,而无法以任何方式涉及数据库。

如果您的服务可以在多个设备上访问,请注意方法2。 考虑以下情况…

  • 用户使用iPadlogin,发行并存储令牌1。
  • 用户在网站上login。 令牌2发布。 用户注销。
  • 用户尝试使用iPad,令牌1在用户从网站注销之前发出,令牌1现在被认为是无效的。

尽pipe这些也需要数据库存储,但您可能需要查看刷新令牌的概念。

在这里也可以看到关于类似问题的讨论,特别是IanB的解决scheme,它可以节省一些数据库调用。

build议的解决scheme就我个人来说,这是我的方法…用户身份validation,与访问令牌发出短期(比如15分钟)和刷新令牌有效期更长或无限期。 将此刷新令牌的logging存储在数据库中。

每当用户处于“活动”状态时,每次都发出一个新的authentication令牌(每次有效15分钟)。 如果用户超过15分钟未激活,然后发出请求(因此使用过期的jwt),请检查刷新令牌的有效性。 如果它是有效的(包括数据库检查),然后发出一个新的身份validation令牌。

如果用户在设备上或通过网站“注销”,则同时销毁访问刷新令牌客户端,重要的是撤销所使用的刷新令牌的有效性。 如果用户在任何设备上更改密码,则撤销其所有刷新令牌,迫使他们在访问令牌到期后再次login。 这确实留下了一个“不确定的窗口”,但这是不可避免的,每次都没有达到分贝。

如果需要的话,使用这种方法还可以使用户能够“撤销”对特定设备的访问,这与许多主要的networking应用程序一样。

我不知道我是否在这里错过了一些东西,但是我发现接受的答案比必要的更复杂。

我看到,必须击中分贝validation或无效的每个API请求令牌,但整个过程可能更简单,因为我在这里看到的东西。

每当创build一个jwt时,即在login或更改/重置密码时,将带有userid的jwt插入到表中,并为每个jwt保留一个jti(基本上是一个uuid数字)。 同样的jti也进入jwt载荷。 有效的jti唯一标识一个jwt。 当多个设备或浏览器访问帐户时,用户可以同时拥有多个jwts,在这种情况下,jti区分设备或用户代理。

所以表格模式是jti | 用户名。 (和课程的主要关键)

对于每个api,检查jti是否在表中,这意味着jwt是有效的。

当用户更改或重置密码时,从数据库中删除该userId的所有jti。 用一个新的jti创build并插入一个新的jwt到表中。 这将使所有其他设备和浏览器的所有会话无效,除了更改或重置密码的设备。

当用户注销时,删除该用户的特定jti,但不是全部。 将有一个单一的login,但不是一个单一的注销。 所以当用户注销时,他不应该从所有设备注销。 但是,删除所有jtis也会从所有设备注销。

所以这将是一个表,并没有date比较。 而且,如果使用刷新令牌,情况也是如此。

但是为了尽量减less数据库干扰和可能的延迟,高速caching的使用肯定会有助于减轻处理时间。

注意:如果你投了票,请原谅。

如果用户正在更改密码,那么您将在那里打开数据库。 但不想打到数据库授权?

我已经发现存储每个用户string的好处,全局共享string散列在一起给了我们最灵活的JWT实现。 在这种特殊情况下,我会存储密码的散列以便与全局string一起使用,并将它们混合在一起以获得JWT秘密。

我完全同意@gopinath的回答只是想添加一件事情,你也应该删除所有令牌过期的更改密码时间,例如假设你已经设置了3天过期时间,每个令牌现在过期,而不是只是正常地保存更改在数据库中的密码时间,你也可以设置其过期时间为3天,因为在这之前明显令牌将会过期,所以不需要再次检查每个令牌是否到期时间是否更长,然后更改密码时间