我正在寻找实现“忘记密码”功能的最佳方法。
我提出了两个想法:
当用户单击“忘记密码”时,要求用户键入用户名,电子邮件,并可能输入出生日期或姓氏。然后,带有临时密码的邮件将被发送到用户的电子邮件帐户。用户使用临时密码登录并重置密码。
与之类似,但电子邮件中将包含一个链接,以使用户重设密码。
还是有人可以建议我一种更好,更安全的方法?我也在考虑发送临时密码或链接,强制用户在24小时内重设密码,否则临时密码或链接将无法使用。怎么做?
我正在寻找实现“忘记密码”功能的最佳方法。
我提出了两个想法:
当用户单击“忘记密码”时,要求用户键入用户名,电子邮件,并可能输入出生日期或姓氏。然后,带有临时密码的邮件将被发送到用户的电子邮件帐户。用户使用临时密码登录并重置密码。
与之类似,但电子邮件中将包含一个链接,以使用户重设密码。
还是有人可以建议我一种更好,更安全的方法?我也在考虑发送临时密码或链接,强制用户在24小时内重设密码,否则临时密码或链接将无法使用。怎么做?
Answers:
更新:2013年5月修订,以寻求更好的方法
password_change_requests
与列ID
,Time
和UserID
。当新用户按下按钮时,将在表中创建一条记录。该Time
列包含用户按下“忘记密码”按钮的时间。该ID
是一个字符串。创建一个长随机字符串(例如,GUID),然后像密码一样对其进行哈希处理(这本身就是一个单独的主题)。然后,将此哈希用作表中的“ ID”。http://www.mysite.com/forgotpassword.jsp?ID=01234567890ABCDEF
。forgotpassword.jsp页面应该能够检索ID参数。抱歉,我不懂Java,所以我不能更具体。ID
从URL中检索,再次对其进行哈希处理,然后对照该表进行检查。如果存在这样的记录,并且该记录不超过24小时,则提示用户输入新密码。ID
,UserID
,Time
,TokenHash
。你会产生两个长,随机字符串将第一个字符串(“ID”)在ID
列;哈希第二(以下简称“令牌” ),然后将哈希值放在TokenHash
列中。生成的链接类似,链接中forogotPassword.jsp?id=asdasd&token=asdasd
的令牌未进行哈希处理。现在有意义吗?
这完全取决于您的站点和您要达到的安全级别,但是Web应用程序的基本过程如下所示:
用户导航到“忘记密码”页面,并输入其用户名或电子邮件(以唯一的为准)以请求重设密码。
(可选)在此阶段,您可以通过询问其他信息(例如预定义的安全问题的答案或他们的生日等)来确认请求。此额外级别可阻止用户接收他们未请求的电子邮件。
查找用户的帐户。保存一个临时密码(通常为GUID)并为帐户记录添加时间戳。向用户发送包含临时密码的电子邮件。
用户或者单击电子邮件中包含临时密码和用户标识符的链接,或者导航到“忘记密码”页面,然后复制并粘贴临时密码及其标识符。用户输入新密码并进行确认。
查找用户的记录,如果当前时间在步骤2中保存的时间戳的指定时间限制内(例如1小时),则哈希并保存新密码。(仅在临时密码匹配时才可以!)。删除临时的GUID和时间戳。
这里的原则是向用户发送一个临时密码,让他们更改密码。最初存储的密码(应哈希!)永远不会更改为临时密码,以防用户记住。
原始密码将永远不会显示给用户,因为它应该是哈希值并且是未知的。
请注意,此过程完全取决于用户电子邮件帐户的安全性。因此,这取决于您希望达到的安全级别。对于大多数网站/应用程序而言,这通常就足够了。
特洛伊·亨特(Troy Hunt)在他的文章《构建安全密码重置功能的所有您想知道的东西》中提出了一些很好的观点。最相关的摘录是:
[T]以下是两种常见方法:
- 在服务器上生成新密码并通过电子邮件发送
- 通过电子邮件发送唯一的URL,这将有助于重置过程
尽管有许多相反的指导,但第一点实际上并不是我们想要达到的目标。这样做的问题在于,这意味着永久密码(您可以随时使用并可以随时使用的密码)已经通过不安全的通道发送并驻留在您的收件箱中。
...
但是第一种方法还有一个更大的问题,那就是它使对帐户的恶意锁定变得简单。如果我知道某人在某个网站上拥有一个帐户的电子邮件地址,那么只要我愿意,只需重置其密码即可将他们锁定在该帐户之外;这是拒绝服务攻击的结果。这就是为什么只有在成功验证请求者的权限后才进行重置的原因。
当我们谈论重置URL时,我们所谈论的是此重置过程的特定实例唯一的网站地址。
...
我们要做的是创建一个唯一的令牌,该令牌可以作为重置URL的一部分发送到电子邮件中,然后与用户帐户旁边的服务器上的记录进行匹配,从而确认电子邮件帐户所有者确实是尝试重置该帐户的所有者。密码。例如,令牌可以是“ 3ce7854015cd38c862cb9e14a1ae552b”,并且与执行重置的用户的ID和生成令牌的时间一起存储在表中(此刻会更多)。发送电子邮件时,其中包含URL,例如“ Reset /?id = 3ce7854015cd38c862cb9e14a1ae552b”,当用户加载该URL时,页面会检查令牌的存在并因此确认用户身份并允许密码被改变。
...
我们想对重置URL进行的另一件事是对令牌进行时间限制,以便重置过程必须在一定时间内(例如一小时内)完成。
...
最后,我们要确保这是一个一次性的过程。重置过程完成后,应删除令牌,以便重置URL不再起作用。与上一点一样,这是为了确保攻击者拥有一个非常有限的窗口,他们可以在其中滥用重置的URL。另外当然,如果重置过程已成功完成,则不再需要令牌。
他在避免信息泄漏,验证码,两因素身份验证,以及基本的最佳实践(例如密码哈希)方面提出了很多其他要点。我认为重要的是要指出,我不同意特洛伊关于安全性问题的用处,而更喜欢布鲁斯·施耐尔(Bruce Schneier)对这种做法的怀疑:
所有这些问题的重点是相同的:备份密码。如果您忘记了密码,这个秘密问题可以验证您的身份,以便您选择其他密码或让网站通过电子邮件将您的当前密码发送给您。从客户服务的角度来看,这是一个好主意-与一些随机密码相比,用户不太可能忘记自己的第一个宠物的名字-但对于安全性而言却很糟糕。这个秘密问题的答案比一个好的密码更容易猜测,而且信息更加公开。
我会去:
通过电子邮件发送任何信息时,它是不安全的。有人可以通过多种方式获得它。对于希望窃取您的信息的熟练黑客来说,这将是小孩子的游戏。
请勿通过电子邮件发送任何个人信息,例如密码和收入信息,因为如果这些信息泄漏或被盗,对您和您的组织而言,这将变得非常困难。认真考虑安全性。只需发生一次事件,所有积木就掉下来。
至于密码检索,请仔细阅读《忘记密码最佳实践》。
最重要的是,遵循最佳实践的应用程序应允许用户重置自己的密码。应该使用人身安全问题。该应用程序不应发送电子邮件,显示密码或设置任何临时密码。
编辑:更新的链接
这是三个非常好的链接,它们提供有关密码重置的信息:
http://jtauber.com/blog/2006/03/20/account_management_patterns/
(不要让用户使用GET进行确认):http : //www.artima.com/forums/flat.jsp? forum=106&thread=152805&start=15&msRange =15
http://fishbowl.pastiche.org/archives/docs/PasswordRecovery.pdf
希望有帮助。他们肯定帮助我理解了这个问题。
切勿通过电子邮件将密码发送给用户。即使它是自动生成的。最佳方法(SANS和其他人推荐和使用):
如果他没有在24小时左右内单击链接,请禁用该链接(以使其不再更改密码)。
未经用户同意,切勿更改密码。这意味着不要仅仅因为有人单击“忘记密码”链接并弄清楚帐户名而通过电子邮件发送新密码。