165

I'm looking for the best method to implement a "forgot password" feature.

I come out with 2 ideas:

  1. When user click on forgot password, the user is required to key in the username, email and maybe date of birth or last name. Then a mail with temporary password will be sent to the user email account. The user uses the temporary password to login and resets his password.

  2. Similar, but the email would contain a link to let the user reset his password.

Or anyone can suggest me a better and secure way? I'm also thinking to send the temporary password or link, force the user to reset the password within 24 hour, or else the temporary password or link will not be usable. How to do that?

4

10 回答 10

204

更新:2013 年 5 月进行了修订,以获得更好的方法

  1. 用户输入他的用户名并点击“忘记密码”。我还建议选择输入电子邮件地址而不是用户名,因为有时也会忘记用户名。
  2. 系统有一个包含和password_change_requestsID的表。当新用户按下按钮时,会在表中创建一条记录。该列包含用户按下“忘记密码”按钮的时间。是一个字符串。创建一个长的随机字符串(例如,一个 GUID),然后像密码一样散列(这本身就是一个单独的主题)。然后将此哈希用作表中的“ID”。TimeUserIDTimeID
  3. 系统向用户发送一封电子邮件,其中包含一个链接。该链接还包含原始 ID 字符串(在散列之前)。该链接将是这样的:http://www.mysite.com/forgotpassword.jsp?ID=01234567890ABCDEF。forgotpassword.jsp 页面应该能够检索 ID 参数。抱歉,我不懂 Java,所以我不能更具体。
  4. 当用户单击电子邮件中的链接时,他将被移至您的页面。该页面ID从 URL 中检索 ,再次对其进行哈希处理,然后对照表进行检查。如果存在这样的记录并且不超过例如 24 小时,则会提示用户输入新密码
  5. 用户输入一个新密码,点击确定,然后每个人都过着幸福的生活……直到下一次!
于 2009-07-09T09:34:59.077 回答
32

这完全取决于您的网站和您尝试实现的安全级别,但 Web 应用程序的基本过程如下所示:

  1. 用户导航到“忘记我的密码”页面并输入他们的用户名或电子邮件(以唯一者为准)以请求重置密码。

  2. 在此阶段,您可以选择通过询问附加信息来确认请求,例如预定义安全问题的答案或他们的出生日期等。这个额外的级别会阻止用户接收他们没有请求的电子邮件。

  3. 查找用户的帐户。根据帐户记录保存临时密码(通常是 GUID)和时间戳。向用户发送包含临时密码的电子邮件。

  4. 用户要么单击电子邮件中包含临时密码和用户标识符的链接,要么导航到“忘记我的密码”页面并复制并粘贴临时密码及其标识符。用户输入他们的新密码并确认。

  5. 查找用户记录,如果当前时间在步骤 2 中保存的时间戳的指定时间限制(例如 1 小时)内,则散列并保存新密码。(显然只有在临时密码匹配的情况下!)。删除临时 GUID 和时间戳。

这里的原则是通过电子邮件向用户发送一个临时密码,让他们更改密码。最初存储的密码(应该是散列的!)永远不会更改为临时密码,以防用户记住它。

原始密码永远不会显示给用户,因为它应该是散列的并且是未知的。

请注意,此过程完全依赖于用户电子邮件帐户的安全性。因此,这取决于您希望达到的安全级别。对于大多数网站/应用程序来说,这通常就足够了。

于 2009-07-09T10:23:24.703 回答
27

Troy Hunt 在他的文章中提出了一些极好的观点,即关于构建安全密码重置功能的所有信息。最相关的摘录是:

[T]这里有两种常见的方法:

  1. 在服务器上生成新密码并通过电子邮件发送
  2. 通过电子邮件发送一个唯一的 URL,这将有助于重置过程

尽管有很多相反的指导,但第一点确实不是我们想要的。这样做的问题在于,它意味着一个永久密码——您可以随时返回并使用该密码——现在已通过不安全的渠道发送并驻留在您的收件箱中。

...

但是第一种方法还有一个更大的问题,因为它使恶意锁定帐户变得非常简单。如果我知道在网站上拥有帐户的人的电子邮件地址,那么我可以随时通过重置他们的密码来锁定他们;它是在银盘上提供的拒绝服务攻击!这就是为什么只有在成功验证请求者的权限后才能进行重置的原因。

当我们谈论重置 URL 时,我们谈论的是重置过程的特定实例所独有的网站地址。

...

我们想要做的是创建一个唯一的令牌,它可以作为重置 URL 的一部分在电子邮件中发送,然后匹配回用户帐户旁边的服务器上的记录,从而确认电子邮件帐户所有者确实是尝试重置的人密码。例如,令牌可能是“3ce7854015cd38c862cb9e14a1ae552b”,并存储在执行重置的用户 ID 和生成令牌的时间旁边的表中(稍后会详细介绍)。发送电子邮件时,它包含一个 URL,例如“Reset/?id=3ce7854015cd38c862cb9e14a1ae552b”,当用户加载它时,页面会检查令牌是否存在,从而确认用户的身份并允许密码被改变。

...

我们想要对重置 URL 做的另一件事是限制令牌的时间,以便重置过程必须在一定的持续时间内完成,比如一个小时内。

...

最后,我们要确保这是一个一次性的过程。重置过程完成后,应删除令牌,以使重置 URL 不再起作用。与前一点一样,这是为了确保攻击者有一个非常有限的窗口,他们可以在其中滥用重置 URL。当然,如果重置过程成功完成,则不再需要令牌。

他在避免信息泄露、验证码、双因素身份验证以及密码散列等基本最佳实践方面提出了更多的好观点。我认为重要的是要注意我不同意特洛伊关于安全问题的有用性,更喜欢布鲁斯施奈尔对这种做法的怀疑

所有这些问题的重点都是一样的:备份密码。如果您忘记了密码,秘密问题可以验证您的身份,因此您可以选择另一个密码或让网站通过电子邮件将您当前的密码发送给您。从客户服务的角度来看,这是一个好主意——与随机密码相比,用户不太可能忘记他的第一只宠物的名字——但安全性却很糟糕。秘密问题的答案比一个好的密码更容易猜到,而且信息更加公开。

于 2012-07-23T19:09:16.750 回答
19

我会去:

  1. 向用户询问电子邮件,检查电子邮件是否已注册
  2. 生成 GUID,并将其发送到该电子邮件
  3. 暂时不要重设密码
  4. 用户点击链接,然后必须输入新的通行证
  5. 仅在用户进入您的站点后重置密码,并在输入新密码后单击重置按钮。
  6. 使该 GUID 在短时间内过期以使其更安全。
于 2010-09-05T00:30:28.170 回答
12

当您通过电子邮件发送任何信息时,它是不安全的。有太多方法有人可以得到它。对于想要窃取您的信息的熟练黑客来说,这将是小菜一碟。

避免通过电子邮件发送任何个人信息,例如密码和收入信息,因为如果此类信息被泄露或被盗,可能会让您和您的组织感到非常尴尬。认真考虑安全问题。只需要一个事件就可以让所有的砖块都掉下来。

至于密码找回,请通读Forgot Password Best Practices

最重要的是,遵循最佳实践的应用程序应该允许用户重置自己的密码。应使用个人安全问题。应用程序不应发送电子邮件、显示密码或设置任何临时密码。

编辑:更新链接

于 2009-07-09T13:12:08.840 回答
8

如前所述,这取决于所需的安全级别,但是,如果您需要更高级别,我见过的一些新颖的解决方案包括:

  • 在确认用户身份(安全问题、电子邮件地址等)后显示一半的临时密码,然后将另一半发送到电子邮件帐户。如果电子邮件帐户已被盗用,则同一个人不太可能还设法执行中间人攻击。(见英国政府门户网站)

  • 通过电子邮件和其他媒介确认身份 - 例如通过文本发送到已注册手机的代码。(在易趣/贝宝上看到)

对于介于这两个极端之间的某个地方,实施安全问题可能是 DaveG 提到的方式。

于 2009-07-09T10:36:06.003 回答
7

If you include an email address with the registration. The "forget password" button sends an email to that email address. It ensures that the information is send to a trusted email.

(Unless the database is hacked, but then nothing is safe).

于 2009-07-09T09:30:08.027 回答
5

我会在帐户中强制使用唯一的电子邮件地址。

然后发送一个链接到一个允许该人更改密码的临时页面是一件简单的事情。(允许 24 小时或更短)

在这种情况下,用户的电子邮件帐户是最薄弱的环节。

于 2009-07-09T13:19:21.700 回答
5

以下是三个非常好的链接,提供有关密码重置的信息:

  1. http://jtauber.com/blog/2006/03/20/account_management_patterns/

  2. (不要让用户使用 GET 确认):http ://www.artima.com/forums/flat.jsp?forum=106&thread=152805&start=15&msRange=15

  3. http://fishbowl.pastiche.org/archives/docs/PasswordRecovery.pdf

希望有帮助。他们确实帮助我理解了这个问题。

于 2011-09-09T14:34:24.827 回答
3

切勿通过电子邮件将密码发送给用户。即使它是自动生成的。最佳方法(由 SANS 和其他人推荐和使用):

  1. 在忘记密码页面上,询问用户的电子邮件/用户 ID 和新密码。
  2. 使用激活链接通过电子邮件发送指向为该帐户存储的电子邮件的链接。
  3. 当用户单击该链接时,启用新密码。

如果他在 24 小时左右没有点击该链接,请禁用该链接(使其不再更改密码)。

未经用户同意,切勿更改密码。这意味着不要仅仅因为有人点击了忘记密码的链接并找出了帐户名而通过电子邮件发送新密码。

于 2009-07-13T18:42:18.947 回答