处理 2FA 代码的过期和验证

Handling expiration & validation of 2FA codes

我目前正在计划实施 2FA,要求用户通过 SMS 为某些操作(例如登录)提供代码。我还将使用 Google Authenticator 等工具,但我不希望用户强制下载该应用程序,这就是为什么我还需要通过短信(或可能是电子邮件)发送验证码的原因。

目前我的计划是:

  1. 用户想要登录并请求代码
  2. 后端生成一个数字代码,将其哈希存储在数据库中,returns 前端数据库条目的 ID(或选择器)
  3. 前端在用户电子邮件和密码旁边显示一个代码输入字段
  4. 代码通过短信/电子邮件发送给用户
  5. 用户现在有 5 分钟的时间将选择器 + 代码 + 电子邮件 + 密码发送到所有这些都得到验证的后端

2 个问题:

1) 处理代码过期

我的第一个想法是将代码仅像密码一样散列存储在数据库中,但我必须自己实施 5 分钟过期。当然,我可以添加另一列带有时间戳的列来检查过期时间,但我宁愿使用更安全的东西。

现在我正在考虑将代码存储在数据库中 json 网络令牌的声明对象中,并将该令牌的到期时间设置为 5 分钟。因此,在 5 分钟结束后,解析网络令牌以将其与用户发送的代码进行比较失败。这将允许我在发生攻击情况时仅更改网络令牌的秘密,并且所有现有代码将立即失效。

这是一个好方法吗?或者你们看到这有什么问题,或者有更好的处理方法吗?或者是否也有一个用于散列具有到期日期的密码的库?

2) 验证和处理暴力攻击

由于我只想向用户发送 6 位或最多 8 位数字代码,因此我必须实施某种保护措施以防止暴力攻击(假设攻击者知道用户的电子邮件和密码).

我想做的事情:

  1. 如果发送了一次无效代码,则增加该特定代码数据库条目的失败尝试次数 += 1
  2. 如果代码超过 3 次失败尝试,则使数据库中的代码无效并要求用户请求新代码
  3. 当用户请求新代码时,让他等待 1 分钟才能请求新代码,将上次尝试失败的日期作为时间戳存储在用户数据库条目中以及 1 分钟延迟
  4. 如果第三个代码失败,存储新的时间戳并将延迟加倍到 2 分钟 ... 等等。 3 次代码失败后,还需要进行 JS 挑战(Google Recaptcha)。
  5. 重试 5 次后我会锁定帐户并等待用户与我们联系。

这是处理代码验证的安全方法吗?

我认为您使用 JWT 过度保护了您的六位数验证码的安全性。

无论您如何管理它们,都必须在它们过期或使用时使它们失效。一个好的方法是在 table 中给每个代码一行,包括过期时间戳。然后在用户显示代码时删除代码行。每当您查找这些代码时,将 WHERE expires > NOW() 添加到查询中。并定期删除过期行。

抵抗暴力攻击很简单。当您准备好向您的用户发送代码时,您已经验证了他们的密码,因此您知道他们假装是谁。因此,只需跟踪该用户猜测代码的尝试即可。按照你的建议,给他们三次尝试。然后让他们请求另一个代码。如果他们在一个日历日内重新请求超过五个代码,将他们锁定到下一个日历日。

顺便说一下,这个方案对于生成各种随机数很有用。 (使用一次的数字。)随机数可用于多种用途,例如通过电子邮件重置密码。