Security 限时或一次性使用密码重置令牌?

Security 限时或一次性使用密码重置令牌?,security,passwords,password-recovery,Security,Passwords,Password Recovery,用户忘记了密码,而且(几乎)所有会员网站都需要一种方法来帮助用户重新登录 我想实现一个常见的场景: 用户点击网站,试图登录,但无法登录,并意识到他们忘记了密码-废话 用户输入电子邮件地址并单击“忘记密码” 用户通过密码重置链接获取电子邮件 下面是我计划如何实现这个(C#/ASP.NET MVC): 当用户输入电子邮件并点击“忘记密码”按钮时,我的网站将生成一个GUID,将其存储在DB中的成员实体上(member.ResetToken),并通过电子邮件向他们发送url中带有该GUID的链接(发送的

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

我想实现一个常见的场景:

  • 用户点击网站,试图登录,但无法登录,并意识到他们忘记了密码-废话
  • 用户输入电子邮件地址并单击“忘记密码”
  • 用户通过密码重置链接获取电子邮件
  • 下面是我计划如何实现这个(C#/ASP.NET MVC):

  • 当用户输入电子邮件并点击“忘记密码”按钮时,我的网站将生成一个GUID,将其存储在DB中的成员实体上(
    member.ResetToken
    ),并通过电子邮件向他们发送url中带有该GUID的链接(发送的电子邮件将通知他们只能使用此链接一次)
  • 用户单击链接,我的网站根据url中的
    成员.ResetToken
    查找他们的帐户。如果找到他们的帐户,则向他们显示密码重置表单,当他们完成重置时,将从他们的帐户中清除
    成员.ResetToken
  • 这里是我的问题:保持这样(他们可以在任何时候、现在或将来使用该链接重置密码)或添加时间戳来限制他们重置密码的时间


    从用户体验的角度来看,随时准备重置密码的功能非常强大,但我想确保我没有忽视这可能会带来的一些安全问题。

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

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

    一、 一个恶意的人,然后可以采取一个巨大的电子邮件地址列表和一个机器人网络和洪水您的服务器与密码重置请求和锁定您的用户从他们的帐户。当然,你的用户会收到一封重置的电子邮件,但是如果我能足够快地重置密码,可能会有积压的电子邮件(或者,如果你同步执行,我可能会关闭整个应用程序)

    一、 您系统的普通用户可能会尝试重置我的密码,但由于我甚至不知道垃圾邮件文件夹(或者它从未到达),因此无法理解为什么我没有收到重置电子邮件。幸运的是,我只记得密码是什么,但它不再工作,因为密码现在是一个不透明的GUID,我基本上死在水里,直到我能找到重置电子邮件

    以下是您应该使用的流程

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

  • 此外,为了防止这种情况已经发生,请确保您正在对用户密码进行哈希和盐析。听起来,您在用GUID替换密码时并没有这样做,所以请仔细检查。

    我会提出以下建议:

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

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

    您还可以考虑要求验证码,这使得暴力攻击和应用程序DoS攻击更加困难

  • 尽快使一次性令牌过期。在我看来,几个小时就足够了。你不应该认为电子邮件是私人的——它不是,除非你在基础协议之上使用一个安全的电子邮件技术(例如PGP)(大多数人不这样做)。你最不希望看到的是黑市打开,在那里买卖你的guid,如果guid有无限的寿命,这正是可能发生的事情

  • 不要使用guid。它们不是随机加密的,是可以猜测的。我建议您使用加密随机数生成器并将其转换为base64


  • 你的计划确实有效,但还有一些地方需要改进。但首先是关于时限的原始问题:

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

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

    最重要的改进是,您应该只在数据库中存储令牌的散列。有权访问数据库(SQL注入)的人可能会