14

我正在做一个允许用户重置密码的模块。我注意到大多数网站如何提供确认链接,其中包含具有唯一哈希的查询字符串。

我的问题是:每次同一个用户请求忘记密码时,如何生成这个唯一的哈希?我应该将此哈希存储在数据库中并稍后将其用于验证吗?会安全吗?或者我应该创建某种生成一次性密码的算法?如何生成 OTP?

4

4 回答 4

30

是的你应该

  1. 生成随机重置令牌。参见例如这个答案
  2. 将其存储在数据库中(可能有到期时间)
  3. 使用重置令牌向用户发送电子邮件。
  4. 用户使用查询字符串中的重置令牌访问重置密码页面。
  5. 检查数据库以查看与重置令牌关联的用户以及到期时间是否尚未过去。
  6. 如果一切正常,允许用户重置密码并从数据库中删除重置令牌。

关于重置令牌(或任何您想称呼它的名称)的生成似乎有很多困惑。请阅读我链接到的答案,不要用散列和弱种子重新发明轮子。

于 2010-08-24T15:50:32.817 回答
3

只需使用一些带有用户 ID、用户盐的哈希函数(你给用户的密码加盐,对吗?)和伪随机数据应该没问题:

$pwd_reset_hash = hash ( 'sha256' , $user_id . $user_salt, uniqid("",true));

将其存储在数据库中(连同请求时间)作为该用户的重置键

 user_id  pwd_reset_hash  time_requested  
===========================================  
 123      ae12a45232...   2010-08-24 18:05

当用户尝试使用它时,检查哈希值是否与用户匹配并且时间是最近的(例如“重置代码在 3 小时内有效”或类似的东西)

使用或过期时将其从数据库中删除

于 2010-08-24T15:51:32.240 回答
1

要走的路确实是生成某种随机的东西并将其存储在数据库中。一旦更改密码,您就从表中删除相关记录,以便无法再次使用该链接。

  • 将 url 邮寄给用户,包括“令牌”。
  • 如果链接被访问,检查token是否存在,允许用户修改密码
  • 从数据库中删除令牌。

正如在其他回复中已经说过的那样,对用户 ID 执行 SHA1 或 MD5,结合微时间和一些盐字符串通常是一个安全的选择。

于 2010-08-24T15:53:09.750 回答
0

1) 要生成唯一的哈希,混合当前时间、用户 ID 和一些盐(文本)。例如,如果您的网站是 mysite.com,则使用以下代码:

 $hash = md5(time() . $userid . 'mysite');

这将创建一个不错的哈希。

2)是的,将其存储在数据库中。
3) 是的,只要你在一段固定的时间后过期哈希,它就会是安全的。
4) 不,生成一次性密码通常会惹恼用户。

于 2010-08-24T15:50:46.870 回答