“忘记密码”的最佳方法 执行?

发布于 2024-07-26 10:21:25 字数 298 浏览 5 评论 0原文

我正在寻找实现“忘记密码”功能的最佳方法。

我提出了两个想法:

  1. 当用户单击“忘记密码”时,用户需要输入用户名、电子邮件,可能还有出生日期或姓氏。 然后一封带有临时密码的邮件将发送到用户的电子邮件帐户。 用户使用临时密码登录并重置密码。

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

或者有人可以建议我一种更好、更安全的方法吗? 我也在考虑发送临时密码或链接,强制用户在24小时内重置密码,否则临时密码或链接将无法使用。 怎么做?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

我早已燃尽 2024-08-02 10:21:25

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

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

Update: revised in May 2013 for a better approach

  1. The user enters his username and hits "forgot password". I also recommend the option of entering the email address instead of the username, because usernames are sometimes forgotten too.
  2. The system has a table password_change_requests with the columns ID, Time and UserID. When the new user presses the button, a record is created in the table. The Time column contains the time when the user pressed the "Forgot Password" button. The ID is a string. A long random string is created (say, a GUID) and then hashed like a password (which is a separate topic in and of itself). This hash is then used as the 'ID' in the table.
  3. The system sends an email to the user which contains a link in it. The link also contains the original ID string (before the hashing). The link will be something like this: http://www.mysite.com/forgotpassword.jsp?ID=01234567890ABCDEF. The forgotpassword.jsp page should be able to retrieve the ID parameter. Sorry, I don't know Java, so I can't be more specific.
  4. When the user clicks the link in the email, he is moved to your page. The page retrieves the ID from the URL, hashes it again, and checks against the table. If such a record is there and is no more than, say, 24 hours old, the user is presented with the prompt to enter a new password.
  5. The user enters a new password, hits OK and everyone lives happily ever after... until next time!
一百个冬季 2024-08-02 10:21:25

这完全取决于您的网站以及您想要实现的安全级别,但网络应用程序的基本流程如下所示:

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

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

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

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

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

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

原始密码永远不会向用户显示,因为它应该经过哈希处理且未知。

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

It all depends on your site and the level of security that you're trying to achieve but the basic process for a web app goes something like the following:

  1. The user navigates to the 'forgot my password' page and enters their username or email (whichever is unique) to request a password reset.

  2. Optionally at this stage you can confirm the request by asking for additional information such as the answer to a predefined security question or their date of birth etc. This extra level stops users receiving emails they didn't request.

  3. Look up the user's account. Save a temporary password (usually a GUID) and timestamp against the account record. Send an email to the user containing the temporary password.

  4. The user either clicks on the link containing the temporary password and the user's identifier in the email or navigates to the 'forgot my password' page and copy & pastes the temporary password and their identifier. The user enters their new password and confirms it.

  5. Look up the user's record and if the current time is within a specified time limit (e.g. 1 hour) of the timestamp saved in step 2 then hash and save the new password. (Obviously only if the temporary passwords match!). Delete the temporary GUID and timestamp.

The principal here is that the user is emailed a temporary password that let's them change their password. The originally stored password (it should be hashed!) is never changed to a temporary password in case the user remembers it.

The original password will never be displayed to the user as it should be hashed and unknown.

Note this process relies entirely on the security of the user's email account. So it depends on the level of security your wish to achieve. This is usually enough for most sites/apps.

自找没趣 2024-08-02 10:21:25

Troy Hunt 在他的文章中提出了一些精彩的观点,您想知道的一切关于构建安全的密码重置功能。 最相关的摘录是:

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

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

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

...

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

当我们谈论重置 URL 时,我们谈论的是对于重置过程的特定实例而言唯一的网站地址。

...

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

...

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

...

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

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

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

Troy Hunt makes some excellent points in his article, Everything you ever wanted to know about building a secure password reset feature. The most relevant excerpts are:

[T]here are two common approaches:

  1. Generate a new password on the server and email it
  2. Email a unique URL which will facilitate a reset process

Despite plenty of guidance to the contrary, the first point is really not where we want to be. The problem with doing this is that it means a persistent password – one you can go back with and use any time – has now been sent over an insecure channel and resides in your inbox.

...

But there’s one more big problem with the first approach in that it makes the malicious lockout of an account dead simple. If I know the email address of someone who owns an account at a website then I can lock them out of it whenever I please simply by resetting their password; it’s denial of service attack served up on a silver platter! This is why a reset is something that should only happen after successfully verifying the right of the requestor to do so.

When we talk about a reset URL, we’re talking about a website address which is unique to this specific instance of the reset process.

...

What we want to do is create a unique token which can be sent in an email as part of the reset URL then matched back to a record on the server alongside the user’s account thus confirming the email account owner is indeed the one attempting to reset the password. For example, the token may be “3ce7854015cd38c862cb9e14a1ae552b” and is stored in a table alongside the ID of the user performing the reset and the time at which the token was generated (more on that in a moment). When the email is sent out, it contains a URL such as “Reset/?id=3ce7854015cd38c862cb9e14a1ae552b” and when the user loads this, the page checks for the existence of the token and consequently confirms the identity of the user and allows the password to be changed.

...

The other thing we want to do with a reset URL is to time limit the token so that the reset process must be completed within a certain duration, say within an hour.

...

Finally, we want to ensure that this is a one-time process. Once the reset process is complete, the token should be deleted so that the reset URL is no longer functional. As with the previous point, this is to ensure an attacker has a very limited window in which they can abuse the reset URL. Plus of course the token is no longer required if the reset process has completed successfully.

He makes many more good points about avoiding information leaks, CAPTCHAs, two-factor authentication, and of course the basic best practices like password hashing. I think it's important to note that I disagree with Troy on the usefulness of security questions, preferring Bruce Schneier's skepticism of the practice:

The point of all these questions is the same: a backup password. If you forget your password, the secret question can verify your identity so you can choose another password or have the site e-mail your current password to you. It's a great idea from a customer service perspective -- a user is less likely to forget his first pet's name than some random password -- but terrible for security. The answer to the secret question is much easier to guess than a good password, and the information is much more public.

指尖上的星空 2024-08-02 10:21:25

我会这样做:

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

I'll go with:

  1. Ask user for email, check email is registered
  2. Generate GUID, and send it to that email
  3. Do not reset password yet
  4. User clicks link, and then have to enter new pass
  5. Reset password only after user is in your site, and have clicked reset button after typing new pass.
  6. Make that GUID expirable within a short time period to make it safer.
荭秂 2024-08-02 10:21:25

当您通过电子邮件发送任何信息时,它并不安全。 人们可以获得它的方法太多了。 对于熟练的黑客来说,想要窃取您的信息简直就是小儿科。

请勿通过电子邮件发送密码和收入信息等任何个人信息,因为如果此类信息泄露或被盗,您和您的组织可能会变得非常尴尬。 认真考虑安全问题。 只需这一次事件,所有的砖块都会倒塌。

关于密码找回,请仔细阅读忘记密码最佳实践

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

编辑:更新了链接

When you are sending any information via email, it won't be secure. There are too many ways someone can get it. It would be child's play for a skilled hacker looking to steal your information.

Refrain from sending any personal information like passwords and income information via email as it can become VERY EMBARRASSING for you and your organization if such information was leaked or stolen. Think about security seriously. It just takes that one incident for all the bricks to fall.

As for password retrieval, thoroughly read Forgot Password Best Practices.

The bottom line is that an application
following best practices should allow
a user to reset his own password.
Personal security questions should be
used. The application should not send
email, display passwords, nor set any
temporary passwords.

EDIT: Updated link

所有深爱都是秘密 2024-08-02 10:21:25

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

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

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

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

As said, it depends on the level of security required, however, if you need a higher level, some novel solutions I have seen include;

  • Displaying half of the temporary password when the user's identity has been confirmed (security question, email address etc.) then the other half being sent to the email account. If the email account has been compromised, it is unlikely that the same person has also managed to perform a man-in-the middle attack. (Seen on UK Goverment Gateway)

  • Confirming identity via email and another medium - for example a code sent via text to a registered mobile. (Seen on eBay / PayPal)

For somewhere in between these two extremes implementing security questions may be the way to go as mentioned by DaveG.

土豪 2024-08-02 10:21:25

如果您在注册时包含电子邮件地址。 “忘记密码”按钮会向该电子邮件地址发送一封电子邮件。 它确保信息发送到受信任的电子邮件。

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

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).

挖个坑埋了你 2024-08-02 10:21:25

我会在各个帐户中强制执行唯一的电子邮件地址。

然后,只需发送一个指向临时页面的链接即可允许该人更改密码。 (允许 24 小时或更短时间)

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

I would enforce unique email addresses across the accounts.

Then it is a simple matter of sending a link to a temporary page that allows the person to change their password. (allow 24 hours or less)

The user's email account is the weakest link in this scenario.

陪你搞怪i 2024-08-02 10:21:25

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

  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

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

Here are three very good links that provide information on password resets:

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

  2. (Don't let users confirm using 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

Hope that helps. They sure helped me understand the issue.

朕就是辣么酷 2024-08-02 10:21:25

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

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

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

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

Never email a password to the user. Even if it is auto-generated. Best approach (recommend and used by SANS and others):

  1. On the forgot password page, ask
    the email/user id and a NEW password
    from the user.
  2. Email a link to the stored email
    for that account with an activation
    link.
  3. When the user clicks on that link,
    enable the new password.

If he doesn't click the link within 24 hours or so, disable the link (so that it does not change the password anymore).

Never change the password without the user consent. It means do not email a new password just because someone clicked on the forgot password link and figured out the account name.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文