如何在 Node.js 中正确实现“忘记/重置密码”功能?(使用一次性令牌)

Two*_*ses 7 javascript security forgot-password node.js jwt

我正在使用 NestJs 在 Node.js 应用程序中实现忘记/重置密码功能。

这就是一般流程:

  1. 用户在“忘记密码”表单中输入电子邮件并提交请求
  2. 服务器生成一个以用户 ID 作为负载的 jwt 令牌,然后发送一封包含该令牌作为重置密码链接的电子邮件(例如: GET: example.com/reset/generated_jwt_token
  3. 用户单击电子邮件中的链接,呈现重置密码页面,他使用新密码填写表单并以密码作为正文提交表单(例如:POST example.com/reset/generated_jwt_token:)
  4. 服务器验证令牌(未过期+有效负载中的用户 ID 存在于数据库中)并更新密码。

这种方法的主要问题是 jwt 令牌可以无限次地使用来重置密码(直到 X 分钟后过期)。

有办法解决这个问题吗?有人说将当前密码的哈希值作为有效负载,因为它无论如何都会被更改并保证 1 次使用,但我不喜欢这种方法。

编辑:我遇到的另一种方法是在 jwt 令牌的数据库中创建一个黑名单集合,该集合不能多次使用。或者以同样的方式在redis中使用缓存,但似乎扩展性不太好。

Cer*_*nce 8

生成令牌后,您可以将其(或其中嵌入的唯一内容)保存到该用户下的数据库中。然后,服务器验证令牌:

(1) 当点击重置密码的链接时

(2)当用户提交重置密码页面时

通过检查该令牌是否与数据库中该用户的令牌相同。

此外,当用户成功更改密码后,请从数据库中清除令牌,以便无法再次使用。