“忘记密码”实施的最佳途径?

我正在寻找实施“忘记密码”function的最佳方法。

我有两个想法:

  1. 当用户点击忘记密码时,用户需要input用户名,电子邮件,可能是出生date或姓氏。 然后一个带有临时密码的邮件将被发送到用户的电子邮件帐户。 用户使用临时密码login并重置他的密码。

  2. 类似的,但电子邮件将包含一个链接,让用户重置他的密码。

或者任何人都可以build议我一个更好和更安全的方式 我也想发送临时密码或链接,强制用户在24小时内重置密码,否则临时密码或链接将不可用。 怎么做?

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

  1. 用户input他的用户名并点击“忘记密码”。 我还build议您input电子邮件地址而不是用户名,因为用户名有时也会被忘记。
  2. 系统有一个表password_change_requests与列IDTimeUserID 。 当新用户按下button时,表中将创build一条logging。 Time栏包含用户按下“忘记密码”button的时间。 该ID是一个string。 一个长的随机string被创build(比如一个GUID),然后像密码一样散列 (这本身就是一个单独的主题)。 然后这个散列用作表中的“ID”。
  3. 系统发送一封电子邮件给用户,其中包含一个链接。 该链接还包含原始IDstring(在散列之前)。 链接将是这样的: http://www.mysite.com/forgotpassword.jsp?ID=01234567890ABCDEF : http://www.mysite.com/forgotpassword.jsp?ID=01234567890ABCDEF 。 forgetpassword.jsp页面应该能够检索ID参数。 对不起,我不知道Java,所以我不能更具体。
  4. 当用户点击电子邮件中的链接时,他将被移动到您的页面。 该页面从URL中检索ID ,再次散列,并对照表格进行检查。 如果有这样的logging,并且不超过24小时,则向用户提示input新密码
  5. 用户input一个新的密码,点击确定,每个人都过着幸福的生活……直到下一次!

这一切都取决于你的网站和你想要实现的安全级别,但是一个Web应用程序的基本过程如下所示:

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

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

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

  4. 用户在电子邮件中点击包含临时密码和用户标识符的链接,或者导航到“忘记我的密码”页面,复制并粘贴临时密码及其标识符。 用户input新密码并确认。

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

这里的主要原因是用户通过电子邮件发送临时密码,让他们更改密码。 原来存储的密码(应该是散列的!)永远不会变成临时密码,以防用户记住密码。

原始密码永远不会显示给用户,因为它应该被哈希和未知。

请注意,此过程完全依赖于用户电子邮件帐户的安全性。 所以这取决于你希望达到的安全水平。 这对大多数网站/应用程序来说通常是足够的

我会去:

  1. 询问用户的电子邮件,检查电子邮件已注册
  2. 生成GUID,并将其发送到该电子邮件
  3. 不要重置密码
  4. 用户点击链接,然后必须input新的通行证
  5. 只有在用户在您的网站后重置密码,并input新的密码后点击重置button。
  6. 使该GUID在短时间内过期以使其更安全。

特洛伊·亨特(Troy Hunt)在他的文章中提出了一些优秀的观点, 你想知道的关于构build安全密码重置function的一切 。 最相关的摘录是:

这里有两种常用的方法:

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

尽pipe有相当多的指导,第一点实际上不是我们想要的地方。 这样做的问题是,它意味着一个永久密码 – 一个可以返回并随时使用的密码 – 现在已经通过一个不安全的频道发送,并驻留在收件箱中。

但是第一种方法存在一个更大的问题,那就是使得账户的恶意locking变得简单。 如果我知道在网站上拥有帐户的人的电子邮件地址,那么只要我简单地通过重置他们的密码,我就可以将其locking在外面。 这是拒绝服务攻击银盘上服务! 这就是为什么重置是在成功validation请求者的权利之后才发生的。

当我们谈论重置URL时,我们正在讨论这个重置过程的特定实例所特有的网站地址。

我们想要做的是创build一个唯一的令牌,可以通过电子邮件发送,作为重置URL的一部分,然后再匹配服务器上的用户帐户旁边的logging,从而确认电子邮件帐户拥有者确实是试图重置密码。 例如,令牌可以是“3ce7854015cd38c862cb9e14a1ae552b”,并且与进行重置的用户的ID以及令牌的产生时间(稍后更多)一起被存储在表格中。 当电子邮件发出时,其包含诸如“Reset /?id = 3ce7854015cd38c862cb9e14a1ae552b”的URL,并且当用户加载该页面时,页面检查令牌的存在并因此确认用户的身份并允许密码被改变。

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

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

他在避免信息泄漏,CAPTCHA,双重身份validation,当然还有密码散列等基本的最佳实践方面做得更多。 我认为重要的是要注意,我不同意特洛伊关于安全问题的用处,宁愿布鲁斯·施奈尔对这种做法持怀疑态度 :

所有这些问题的重点是相同的:备份密码。 如果您忘记密码,这个秘密问题可以validation您的身份,以便您可以select另一个密码或让该网站通过电子邮件将您当前的密码发送给您。 从客户服务的angular度来看,这是个好主意 – 用户不太可能忘记他的第一个宠物的名字,而不是一些随机的密码,但是为了安全起见,这很糟糕。 这个秘密问题的答案比一个好的密码要容易得多,而且信息更公开。

当您通过电子邮件发送任何信息时,它将不安全。 有人能得到它的方式太多了。 对于一个技术娴熟的黑客来说,窃取你的信息将是孩子们的玩耍。

不要通过电子邮件发送任何个人信息,如密码和收入信息,因为如果这些信息被泄露或被盗,它可能会变得非常尴尬。 认真考虑安全。 所有的砖块都只有一个事件发生。

至于密码检索,请仔细阅读忘记密码最佳实践

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

编辑:更新的链接

如上所述,这取决于所需的安全级别,但是,如果您需要更高的级别,我所看到的一些新颖的解决scheme包括:

  • 当用户的身份已经被确认(安全问题,电子邮件地址等)时显示一半的临时密码,然后另一半被发送到电子邮件帐户。 如果电子邮件账户被盗用,同一个人也不太可能进行中间人攻击。 (见英国政府网关)

  • 通过电子邮件和其他媒体确认身份 – 例如通过文本发送给注册手机的代码。 (在eBay / PayPal看到)

在这两个极端之间的某个地方,执行安全问题可能是DaveG提到的方法。

如果您包含注册的电子邮件地址。 “忘记密码”button向该电子邮件地址发送电子邮件。 它确保信息被发送到可信的电子邮件。

(除非数据库被黑客入侵,但是没有什么是安全的)。

这里有三个非常好的链接提供密码重置信息:

  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. archives/docs/PasswordRecovery.pdf

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

我会执行帐户中唯一的电子邮件地址。

那么发送一个链接到一个临时页面可以让用户修改密码是一件简单的事情。 (允许24小时或更less)

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

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

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

如果他在24小时内没有点击链接,请禁用链接(以免它再次更改密码)。

切勿在未经用户同意的情况下更改密码。 这意味着不要仅仅因为有人点击了忘记的密码链接而find新的密码并找出了账户名称。