这是实现“忘记密码吗?”的好方法吗?特征?

时间:2012-03-12 05:40:25

标签: php forgot-password

我目前正在设计一个小型网站,我想实现“忘记密码?”特征。这是我的想法:

忘了你的密码网页会有这个:

Email: (input box)
(button: "Make temp password")

点击“设置临时密码”按钮:

  1. 清理SQLi / XSS的电子邮件输入
  2. 检查数据库中是否存在电子邮件地址
    • 如果没有,请告诉用户建立新帐户或查看电子邮件拼写
  3. 创建随机密码(即“xh5MvQe”)并将其放入用户临时密码字段的数据库中。
    • 覆盖(如果已存在)。不要触摸主密码。用户将能够在接下来的48小时内使用两个密码登录。
  4. 获取当前UTC时间加上48小时,并将其放入数据库中用户的临时密码到期日期字段中。如果已经存在则覆盖。
  5. 使用临时密码
  6. 向用户发送电子邮件

    我的数据库包含用户表的这些字段:

    (primary key) user id
    name
    nickname
    (non null, unique) email
    (non null) password (encrypted)
    temporary password
    temporary password expiration
    

    用户拥有密码后,即可登录并更改主密码。

    问题是:这是实现此功能的安全方式吗?我主要担心的是通过电子邮件发送纯文本密码。我已经看到了生成带有电子邮件哈希/时间戳/随机ID作为GET参数的链接的另一种方式,但我不知道这是多么安全。如果我错了,请纠正我。

3 个答案:

答案 0 :(得分:4)

阅读本文:The definitive guide to form-based website authentication

向用户发送任何密码是不好的,因为您无法确定他的计算机/电子邮件帐户是否安全。如果您生成并发送密码,则用户可能不会更改密码。你不能避免发送某种识别令牌进行恢复,所以到期日是一个好主意。

切勿在任何地方存储普通密码。使用盐渍哈希。攻击者访问您的数据库是非常糟糕的,但对于使用相同密码进行其他服务的用户来说情况更糟 - 他们总是这样做,愚蠢的用户。

因此,这是一种避免在用户计算机上保存纯文本密码的方法:

  1. 清理SQLi / XSS的电子邮件输入
  2. 检查数据库中是否存在电子邮件地址
    • 如果没有,请告诉用户建立新帐户或查看电子邮件拼写
  3. 创建随机恢复登录令牌(即“xh5MvQe”)并将其在数据库中的哈希值放在用户的密码恢复哈希字段中。
    • 覆盖(如果已存在)。不要触摸主密码。用户将能够
      • 使用旧密码登录,删除恢复哈希值。
      • 在接下来的48小时内使用恢复令牌密码登录,这会强制用户选择新密码。
  4. 获取当前UTC时间加48小时[...]
  5. 使用一次性恢复登录令牌链接向用户发送电子邮件。

答案 1 :(得分:1)

我认为您拥有的伪造系统是安全的,我会添加第6步,即在用户更改其实际密码时清除临时密码。如果您担心未加密的电子邮件 - 即使用户成功更改密码,您也需要确保临时密码长达48小时不可用。

答案 2 :(得分:0)

这是非常不寻常的方式 大多数时候发送超链接,而不是密码本身。

一个超链接,允许用户输入另一个密码 由电子邮件和到期时间组成,用一些哈希密封。

此外,我认为对XSS清理电子邮件毫无意义 而“为SQLi清理电子邮件输入”对我来说听起来很奇怪,这是一个单独的步骤。是否必须准备SQL查询创建的本地部分?为什么它碰巧成为全局算法的一部分?

所以,对我而言,它看起来像是两部分算法:

  1. 要求用户输入他们的电子邮件。
  2. 检查数据库中是否存在电子邮件地址
  3. 如果是,请发送指向该电子邮件的超链接
  4. 使用这样的代码

    $salt  = "35onsoi2e=-7#%3%g03skl";
    $time  = time();
    $hash  = MD5($_POST['email'].$time.$salt);
    $email = urlencode($_POST['email']);
    $link  = "http://example.com/register.php?email=$email&time=$time&hash=$hash";
    

    点击链接后,用户登陆恢复密码脚本,

    1. 验证是否使用相同的散列算法。
    2. 检查到期时间。
    3. 如果一切正常,则提示用户输入新密码
    4. 重置数据库中的密码。