1

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

忘记密码的网页会有这个:

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

在“制作临时密码”按钮上单击:

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

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

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

一旦用户获得密码,他们就可以登录并更改他们的主密码。

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

4

3 回答 3

4

阅读本文:基于表单的网站身份验证的权威指南

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

永远不要在任何地方存储纯密码。使用盐渍哈希。攻击者访问您的数据库已经够糟糕的了,但对于为其他服务使用相同密码的用户来说,情况更糟——而且他们总是这样做,愚蠢的用户。

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

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

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

于 2012-03-12T05:47:16.537 回答
0

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

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

此外,我认为针对 XSS 清理电子邮件毫无意义。
“清理 SQLi 的电子邮件输入”作为单独的步骤对我来说听起来很奇怪。必要的准备不是 SQL 查询创建的本地部分吗?为什么它恰好是全局算法的一部分?

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

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

用这样的代码

$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. 重置数据库中的密码。
于 2012-03-12T06:13:37.950 回答