简体   繁体   English

如何在PHP / MySQL Web应用程序中安全地向用户提供新密码?

[英]How can I securely provide a user with a new password in a PHP/MySQL web application?

I have a simple question. 我有一个简单的问题。 What is the best way to do a password recovery for a user? 为用户恢复密码的最佳方法是什么?

I want the user to be able to click a link like "forget your password?" 我希望用户能够单击“忘记密码?”之类的链接。 When clicked, the user will receive an email with a new password. 单击后,用户将收到一封包含新密码的电子邮件。

I think sending the hash is a bad option, then I must generate a random password, convert to a hash + random salt, replace it in the database and send the new random password by email. 我认为发送哈希是一个不好的选择,然后我必须生成一个随机密码,将其转换为哈希+随机盐,在数据库中替换它,然后通过电子邮件发送新的随机密码。 Is this the best way, or is there another? 这是最好的方法,还是还有另一种方法? Simpler is better. 越简单越好。

Thanks! 谢谢!

The safest way is to email the person a link to a page that allows them to create a new password. 最安全的方法是通过电子邮件向该人发送指向该页面的链接,以允许他们创建新密码。 Passwords should only ever be stored as salted hashes. 密码只能存储为盐渍哈希。 Subverting this process would require that a person's email be compromised -- in which case they've probably got worse problems than a compromised password to your webapp. 颠覆此过程将需要破坏一个人的电子邮件-在这种情况下,与您的Web应用程序的受破坏密码相比,他们可能遇到的问题更严重。


Files and tables: 文件和表:

I imagine that your database contains a table called "users", with a column called "userid" which serves as its primary key. 我想您的数据库包含一个名为“ users”的表,该表具有一个名为“ userid”的列作为其主键。

  1. Create a new table in your tabase called password_reset with three columns: userid , which is a foreign key pointing to the table users ; 在您的Tabase中创建一个名为password_reset的新表,其中包含三列: userid ,它是指向表users的外键; code , which will contain a unique, random number; code ,它将包含一个唯一的随机数; and timestamp , which will contain the date that a request is made. timestamp ,其中将包含发出请求的日期。

  2. Create a page for password resets, like password_reset_request.php . 创建用于密码重置的页面,例如password_reset_request.php Ask for a username or email. 询问用户名或电子邮件。

  3. Create a page for setting a new password, like set_new_password.php . 创建用于设置新密码的页面,例如set_new_password.php

Logic: 逻辑:

  1. If the username or email supplied to password_reset_request.php is valid, insert a row in the password_reset table corresponding to the request. 如果提供给password_reset_request.php的用户名或电子邮件有效,请在password_reset表中与请求相对应的地方插入一行。 Imagine that user Fel has placed a password reset request. 想象一下,用户Fel发出了密码重置请求。 Fel 's internal userid might be 564979 . Fel的内部userid可能是564979 The row in password_reset would be something along these lines: 564979, 54c4a2767c2f485185ab72cdcf03ab59, 2011-01-01 12:00:00 . password_reset的行可能是以下564979, 54c4a2767c2f485185ab72cdcf03ab59, 2011-01-01 12:00:00行: 564979, 54c4a2767c2f485185ab72cdcf03ab59, 2011-01-01 12:00:00

  2. Send an email to the user's email address containing an url looking like this: http://your.url/set_new_password.php?userid=564979&code=54c4a2767c2f485185ab72cdcf03ab59 . 将包含以下网址的电子邮件发送到用户的电子邮件地址: http://your.url/set_new_password.php?userid=564979&code=54c4a2767c2f485185ab72cdcf03ab59

  3. When set_new_password.php gets a hit, it should check for the presence of the userid and code properties in the URL. set_new_password.php被点击时,它应检查URL中是否存在useridcode属性。 Not there? 不在那里? Abort. 中止。

  4. Sanitize the userid and code properties if they're there. 清理useridcode属性(如果存在)。 This is important. 这个很重要。

  5. Run an SQL command like this: SELECT * FROM password_reset pr WHERE pr.userid = $userid AND pr.code = $code AND TIMESTAMPDIFF(DAY, CURTIME(), pr.timestamp) < 1 . 运行这样的SQL命令: SELECT * FROM password_reset pr WHERE pr.userid = $userid AND pr.code = $code AND TIMESTAMPDIFF(DAY, CURTIME(), pr.timestamp) < 1

  6. If you receive no results, Abort. 如果没有结果,则中止。

  7. If you receive a result, allow the user to enter a new password. 如果收到结果,请允许用户输入新密码。

  8. After validating the password as you normally would upon registration, use an SQL UPDATE statement to change the user's password. 在按照通常的注册密码进行验证之后,请使用SQL UPDATE语句更改用户的密码。

  9. Use SQL to delete any requests for the user from the password_reset table: DELETE * FROM password_reset WHERE userid = $userid . 使用SQL从password_reset表中DELETE * FROM password_reset WHERE userid = $userid对该用户的任何请求: DELETE * FROM password_reset WHERE userid = $userid

You're done! 你完成了!

I would do the following 我会做以下

  1. User requests password reset 用户要求重设密码
  2. User enters either username or password 用户输入用户名或密码
  3. An e-mail is sent to the user with a link with a unique hash that is placed in a database table (eg pwrecovery) - this link would be like: http://domain.com/pwrecover.php?key=KEYHERE 一封电子邮件将通过链接发送给用户,该链接带有放置在数据库表中的唯一哈希(例如pwrecovery)-该链接类似于: http ://domain.com/pwrecover.php?key=KEYHERE
  4. The user clicks that link, if the hash exists in the table then they get sent another e-mail with their new password. 用户单击该链接,如果表中存在哈希,则他们会收到另一封包含新密码的电子邮件。

That way, users wont find their password being changed by random users when they get a correct e-mail. 这样,当用户收到正确的电子邮件时,他们将不会发现随机用户会更改其密码。

You should email a link to a page with a security question (and a unique code to prevent people from getting other people's security questions). 您应该通过电子邮件发送到包含安全问题的页面的链接(以及用于防止他人获得其他人的安全问题的唯一代码)。

After answering the question, allow the user to create a new password. 回答问题后,允许用户创建新密码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM