34

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

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

通过电子邮件发送临时密码重置密码

谢谢。

4

9 回答 9

76

可能最简单的方法是修改您的用户表以添加 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 页面验证令牌和过期字段。(IE 确保 DateTime.Now < PasswordResetExpiration)
  5. 提供一个允许用户重置此密码的简单表单。

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

于 2009-12-31T15:35:55.497 回答
2

@亚历克斯

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

using System.Security.Cryptography;
...
var hash = SHA256CryptoServiceProvider.Create().ComputeHash(myTokenToHash);
...
于 2010-10-11T18:34:49.530 回答
1

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

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

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

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 从 URL 中获取它:

if (Request.QueryString["hash"] != null)
{
                //extract Hash from the URL
                string strHash = Request.QueryString["hash"];
}
于 2009-12-31T15:36:18.687 回答
1

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

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

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

这给了你两件事:

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

于 2013-02-26T20:28:00.230 回答
0

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

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

结果:我认为你最好

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

祝你好运。

于 2012-11-30T21:21:26.493 回答
0

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

简单解释一下普通密码盐和散列;假设 salt is1111和 pasword is password,您将连接两者并对字符串进行哈希处理1111password,假设这给了您 的哈希值9999,然后您将原始 salt1111和哈希值存储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 报告错误。

于 2014-07-17T11:23:31.597 回答
0

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

于 2018-08-10T09:31:11.997 回答
-3

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

(UserId)-(ExpireDate)

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

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

于 2009-12-31T15:29:10.003 回答