12

用户忘记了密码,并且(几乎)所有会员网站都需要一种方法来帮助用户重新登录。

我想实现常见的场景:

  1. 用户访问站点,尝试登录,但无法登录,然后意识到他们忘记了密码——废话!
  2. 用户输入电子邮件地址并点击“忘记密码”
  3. 用户收到带有密码重置链接的电子邮件

以下是我打算如何实现它(C#/ASP.NET MVC):

  1. 当用户输入电子邮件并点击“忘记密码”按钮时,我的网站将生成一个 GUID,将其存储在数据库中的成员实体中member.ResetToken(此链接只能使用一次)
  2. member.ResetToken用户单击该链接,我的网站会根据该 url查找他们的帐户。如果找到他们的帐户,请向他们显示密码重置表格,当他们完成重置时,它会member.ResetToken从他们的帐户中清除密码。

这是我的问题:保持这样(他们可以在现在或将来随时使用该链接重置密码)或添加时间戳以限制他们必须重置密码的时间?

从用户体验的角度来看,在您准备好时重置密码的能力很棒,但我想确保我没有忽略这可能引发的一些安全问题。

4

4 回答 4

10

您的方案确实有效,但有些地方可以改进。但首先是关于时间限制的原始问题:

让我们问一个相反的问题:为什么令牌应该无限期保持有效?

没有任何优势,当两年后可以单击重置链接时,用户要么在大约一个小时内单击该链接,要么他可能已经忘记了该链接(并且可以在必要时请求一个新链接)。另一方面,能够阅读电子邮件并不一定意味着攻击者必须破解电子邮件帐户,例如办公室中打开的电子邮件客户端、丢失的手机、在(丢失的)USB驱动器上备份...

最重要的改进是,您应该只在数据库中存储令牌的哈希值。有权访问数据库(SQL 注入)的人可能会要求为他喜欢的任何电子邮件地址重置密码,并且因为他可以看到新令牌,所以他可以使用它来设置自己的密码。

然后我会将这些重置信息存储在一个单独的表中。在那里,您可以存储用户 ID、散列令牌、到期日期以及链接是否已被使用的信息。此时用户并不处于特殊状态。

也许我误解了这一点,但重置链接应该指向一个特殊的密码重置页面。当用户进入登录页面时,应该没有特殊处理,登录页面不应该知道有一个未决的密码重置。

重置令牌应该是不可预测的,这可以通过从操作系统的随机源读取的真正随机代码来实现。

于 2013-10-10T10:47:56.820 回答
2

因此,我在评论中试图避免这种方法存在一些问题。当您将“确认令牌”存储在用户密码中时,您基本上已经销毁了他们的密码。

我,一个恶意的人,然后可以获取一个巨大的电子邮件地址列表和一个僵尸网络,并用密码重置请求淹没你的服务器,并将你的用户锁定在他们的帐户之外。当然,您的用户会收到一封重置密码的电子邮件,但如果我可以足够快地重置密码,则可能会有电子邮件积压(或者,如果您同步执行此操作,我可能会拒绝整个应用程序)。

我,您系统的普通用户,可能会尝试重置我的密码,但无法弄清楚为什么我没有收到重置电子邮件,因为我什至不知道垃圾邮件文件夹(或者它从未到达)。幸运的是,我只记得密码是什么,但它不再起作用了,因为密码现在是一个不透明的 GUID,在我找到重置电子邮件之前,我基本上已经死在水中了。

这是您应该使用的过程。

  1. 生成您使用 GUID 查找的密码重置请求,您可能还可以通过使用一些私有数据对该值进行散列并将其传递到 URL 中来保护它,以避免快速攻击。您还可以通过使其仅在一定时间内有效来锁定此请求。
  2. 一旦有人使用有效令牌和您指定的任何其他参数跟随该链接,他们就可以更改密码,此时您现在可以安全地更改用户密码
  3. 将密码请求标记为已完成,或将其删除。如果您真的很担心谁更改了密码,您也可以跟踪 IP 地址或类似信息等信息。
  4. 向用户发送一封电子邮件,确认他们已更改密码。

此外,以防万一这还没有发生,请确保您正在对用户密码进行散列和加盐处理。当您只是用 GUID 替换密码时,听起来您并没有这样做,所以请仔细检查。

于 2013-10-09T03:20:16.153 回答
1

用户也忘记重置密码(事情发生了)。由于对密码偏执,我建议将链接生命周期限制为 24 小时。这应该绰绰有余。它没有解决恶意拦截的问题,但总比没有好。

于 2013-10-09T03:08:04.477 回答
1

我会提出以下建议:

  1. 在允许用户单击忘记密码按钮之前需要一些信息。例如,需要电子邮件地址和出生日期。

    理想情况下,您的用户界面不应提供任何反馈,让黑客确定他的重置请求是否成功。您不希望他们为电子邮件地址或 DOB 耕种您的页面。然而,这是一个可用性权衡,所以你是否这样做取决于你真正需要多少安全性。

    您可能还考虑需要一个验证码,这使得蛮力和应用程序 DoS 攻击更加困难。

  2. 尽快使一次性令牌过期。在我看来,几个小时就足够了。您永远不应该认为电子邮件是私密的——它不是,除非您在基本协议之上使用安全电子邮件技术(例如 PGP)(大多数人不这样做)。您最不想要的就是打开一个黑市来买卖您的 GUID,如果它们具有无限的生命周期,这正是可能发生的事情。

  3. 不要使用 GUID。它们不是密码随机的并且是可猜测的。我建议您使用加密随机数生成器并将其转换为 base64。

于 2013-10-09T23:43:34.907 回答