【问题标题】:Generate temporary URL to reset password生成临时 URL 以重置密码
【发布时间】:2010-12-31 10:40:39
【问题描述】:

我希望在我的网站上实现忘记密码功能。我喜欢将包含临时一次性使用 URL 的电子邮件发送给用户的选项,该 URL 在一段时间后过期。

我查看了以下页面以获得这些想法,但我不确定如何使用 ASP.NET 和 C# 来实现它。正如其中一位用户所指出的,如果我可以在不将此信息存储在数据库中的情况下实现这一点,那将是理想的。请指教。

Password reset by emailing temporary passwords

谢谢。

【问题讨论】:

    标签: url passwords reset


    【解决方案1】:

    可能最简单的方法是修改您的用户表以添加 2 个额外的列,或者如果您不想修改现有表,您可以添加一个名为“UserPasswordReset”的新依赖表或类似的东西。列是这样的:

    PasswordResetToken UNIQUEIDENTIFIER,
    PasswordResetExpiration DATETIME
    

    如果您使用附加表路由,您还可以添加 UserID 列,将其作为主键和外键引用返回到您的用户表。还建议使用 UNIQUE 约束。然后,您只需在您的 asp.net 应用程序中使用 Guid 作为令牌。

    流程可能是这样的:

    1. 用户请求为其帐户重置密码
    2. 您可以通过将 PasswordResetExpiration 设置为将来的某个日期 (DateTime.Now.AddDays(1)) 在表中插入一条新记录(或更新他们的用户记录),并将令牌设置为 Guid.NewGuid()
    3. 通过电子邮件向用户发送指向您的 ResetPassword.aspx 页面的链接,并在查询字符串中使用 guid (http://www.yoursite.com/ResetPassword.aspx?token=Guid-here)
    4. 使用 ResetPassword.aspx 页面验证令牌和过期字段。 (即确保 DateTime.Now
    5. 提供允许用户重置此密码的简单表单。

    我知道你想避免修改数据库,但这确实可能是最简单的方法。

    【讨论】:

    • 安全注意事项:UNIQUEIDENTIFIER 并不意味着提供随机性,并且在这种情况下是不安全的。基本上,您需要一个无法猜测的重置链接。为了使您无法猜测您的重置链接,您需要包含一个由加密安全随机数生成器生成的随机数,而 GUID 不是。因此,除了您的 2 列之外,您还需要第三列来存储将充当您的密码的随机数,最后您将 GUID 和密码作为参数发送到重置链接中。
    【解决方案2】:

    @亚历克斯

    您还可以将 .NET 中的 System.Security.Cryptography 类用于哈希算法。例如:

    using System.Security.Cryptography;
    ...
    var hash = SHA256CryptoServiceProvider.Create().ComputeHash(myTokenToHash);
    ...
    

    【讨论】:

      【解决方案3】:

      这里是您朋友中的 System.Guid 类,因为它将生成一个唯一(嗯,足够唯一)128 位数字:

      • 生成新的 Guid (System.Guid.NewGuid())
      • 将该 Guid 存储在某处(可能是应用程序对象?)
      • 使用该 Guid 在电子邮件中发送自定义 URL
      • 当用户访问网站时,让他们输入您在电子邮件中发送的密码
      • 如果密码匹配,请继续强制他们输入新密码

      【讨论】:

      • GUID 应该是唯一的,但不应该是强大的加密货币。可能会猜测将创建哪个 GUID,从而为特定帐户创建令牌。
      • @Guillaume,感谢您提供的信息,真的有可能吗?你能解释一下它是如何被猜到的吗?我正在考虑使用 GUID。
      • 这可能需要一个针对 GUID 的单独问题。简而言之,GUID 通常是根据一些可猜测的输入(MAC 地址、时间戳等)和随机部分生成的。难以猜测的部分是随机部分,它不一定很大,因此可能不像提供安全性所应该的那样难以猜测。简而言之:GUID 是唯一的,它们并不难猜。
      • 独特!=随机。 Guid 是可预测的,在需要随机令牌时不应使用。
      【解决方案4】:

      我使用散列类创建由当前日期/时间和用户电子邮件地址组成的唯一自动登录:

      string strNow = DateTime.Now.ToString();
      string strHash = strNow + strEmail;
      strHash = Hash.GetHash(strHash, Hash.HashType.SHA1);
      

      从http://www.developerfusion.com/code/4601/create-hashes-md5-sha1-sha256-sha384-sha512/获取哈希类

      然后从 URL 中获取它:

      if (Request.QueryString["hash"] != null)
      {
                      //extract Hash from the URL
                      string strHash = Request.QueryString["hash"];
      }
      

      【讨论】:

      • 如何再次从哈希中取回电子邮件地址和日期时间,以便自动登录?因为哈希是一种方式,对吗?请教育。
      • @goths 您可以将哈希值存储在数据库中,并发送包含附加用户 ID 和哈希的 URL 的电子邮件。然后在 URL 指向的页面上,将 2 与数据库进行比较。这将是一个基本的解决方案,您需要更强大的东西来满足需要更高安全性的东西。
      • 抱歉,如果关键是将其存储在数据库中的相同信息旁边,我看不到该实用程序在散列编码密钥中发送任何信息。您唯一需要的是唯一的密钥,而不是任何“真实”信息的加密版本。如果您必须将某些内容发送并存储在数据库中以便在用户单击已发送电子邮件中的链接时能够找到它,那么 Goyuix 提出的随机生成的唯一 ID(请参阅他的答案)只是最佳选择。
      • 如何验证哈希?
      【解决方案5】:

      我肯定会在这个过程中包含数据库。一旦请求重置,最好表明该帐户已被锁定。

      例如,如果您更改密码是因为您认为您的帐户可能已被盗用,那么您绝对不希望在进行更改过程时它仍然可以访问。

      此外,如果有人真的想要并且有能力,可以解码重置令牌中包含的“真实”信息。生成一个随机字符串会更安全,将其保存在该用户所在行的数据库中,然后在单击链接时返回给它。

      这给了你两件事:

      1) 没有什么可解密的,因此无法从中获得任何有价值的东西。 2) 用户记录中存在令牌表示正在进行重置,应将帐户视为已锁定。

      【讨论】:

        【解决方案6】:

        向用户电子邮件发送一些数据|字符串的目的是验证帐户所有者。请注意几点:

        • 避免在重置或激活链接中发送重要信息。
        • 与用户一起存储唯一字符串数据的最佳方式 帐户并将其作为该链接发送。但请注意,如果您只发送一个 部分作为用户电子邮件的链接,只需在页面中检查它,您的 应用程序可能因暴力或字典而处于危险状态 攻击者。检查字符串列表以找到一些链接就足够了 并更改密码。我知道有一点机会,但不是零。

        结果: 我觉得最好是你

        1. 将用户电子邮件与字符串链接相结合,然后对其进行加密 (不是散列,因为散列值不能反转)并发送给用户 电子邮件。
        2. 用户点击,您的页面获得加密值。
        3. 解密值。
        4. 提取用户电子邮件。
        5. 在数据库中查找电子邮件。
        6. 将接收到的链接中的字符串与附加到用户的其他链接进行比较 数据库中的电子邮件。

        祝你好运。

        【讨论】:

          【解决方案7】:

          我会使用哈希码来验证密码重置网址中的详细信息。这一切都可以在不向数据库写入任何内容或向攻击者发送任何特权信息的情况下完成。

          简单解释一下普通的密码加盐和散列;假设盐为1111,密码为password,您将连接两者并散列字符串1111password,假设这给了您9999的散列,然后您将存储原始盐@987654325 @ 并在您的用户记录中散列 9999。

          当您验证密码时,您使用存储的盐,连接密码尝试,对其进行散列并与存储的散列进行比较。例如 asecret 变为 1111asecret 但散列为 8888。这与原始哈希不匹配,因此密码匹配失败。

          当然,盐和哈希通常会使用已建立的加密库正确生成和计算(不要自己发明!)。

          对于密码重置 URL,我会输入用户的唯一标识符,即电子邮件地址、发出请求的日期和新的哈希值。这个哈希值是由那些连接在一起的细节加上已经为用户存储的盐和哈希值生成的。

          例如:

          Email: user@example.com
          Request Date: 2014-07-17
          Salt: 1111
          Hash: 9999
          

          生成一个新的哈希值,即'user@example.com2014-07-1711119999',假设这给出了7777的哈希值。

          然后我生成的 URL 将包含电子邮件、请求日期和新哈希:

          https:\\www.example.com\ResetPassword?email=user@example.com&requestdate=2014-07-17&hash=7777
          

          服务器会将电子邮件和提供的日期与它的盐和哈希结合起来,并确认它生成的哈希与提供的相同。如果这没问题,那么它将显示重置表单,其中隐藏了相同的三个参数,否则会出错。当输入新密码以防止该表单被欺骗时,这些将被重新提交并重新检查。

          需要提供电子邮件地址才能提出请求,并且仅通过电子邮件将其发送到同一地址。日期几乎不是特权信息,而且哈希是不可逆的,所以无论如何都没有给出任何信息。没有向数据库写入任何内容,任何篡改参数都会导致哈希失败并且 URL 报告错误。

          【讨论】:

          • 这种方法存在问题。安全的散列使令牌非常长。要么将盐集成到散列本身(使其长约 20 个字符),要么将这个唯一的盐存储在数据库中。如果您将盐存储在数据库中,您还可以存储一个随机令牌,该令牌不是从任何现有数据派生的。
          • @martinstoeckli 由于您已经在连接字符串中散列了盐,因此无需添加另一个。 OP 确实要求它不存储在数据库中。虽然你是对的,但 url 很长,适当的哈希会使它更长,但我希望链接被点击,或者复制和粘贴,所以我认为这不是什么大问题。
          • 我的意思是,盐必须以可读的形式包含在链接中,否则它是键而不是盐。每个令牌的盐是唯一的,它必须存储在数据库中,或者您可以从 url 中提取它。
          • 任何完整的生成哈希和验证哈希的源代码?
          【解决方案8】:

          这种方法存在问题。安全的散列使令牌非常长。要么将盐集成到散列本身(使其长约 20 个字符),要么将这个唯一的盐存储在数据库中。如果您将盐存储在数据库中,您还可以存储一个随机令牌,该令牌不是从任何现有的

          派生的

          【讨论】:

            【解决方案9】:

            根据您的需要,您可以加密信息,格式类似于以下格式

            (UserId)-(ExpireDate)
            

            加密数据,建立链接,然后解密数据并从那里采取行动......

            粗糙,但很可能可用,并且不需要使用数据库

            【讨论】:

            • 将任何数据包含在密码重置令牌中是一种不好的做法。如果它被加密,则事件。知道该算法的黑客即使无法访问用户的邮箱,也可以为任何用户重置密码。
            • -1。这个想法在某种意义上是好的,但由于 Slava 在之前的评论中解释的安全问题,不应该使用它。
            • @SlavaNadvorny 黑客还需要知道加密算法的密钥。你可以假设如果黑客可以访问加密密钥,他可能也可以访问存储的哈希值,所以是的,这种技术似乎仍然是一个好主意。
            • 这种技术的真正问题是它不能防止多次使用同一个重置令牌。
            • @Guillaume 我同意,但是因为它是用户绑定的,这没什么大不了的。如果用户有能力存储到数据库或愿意,那会更容易
            猜你喜欢
            • 2019-09-19
            • 2010-10-19
            • 2011-04-03
            • 2020-12-12
            • 1970-01-01
            • 2018-07-28
            • 2015-07-13
            • 2010-11-21
            • 2010-12-15
            相关资源
            最近更新 更多