【问题标题】:Is there a cleaner way to check a hashed password than this?有没有比这更干净的方法来检查散列密码?
【发布时间】:2017-07-12 20:52:13
【问题描述】:

到目前为止,我如何检查散列密码,如果数据库比家庭/大学中的测试更大,是否有一种方法可以使这个更干净,并且可能更快?

<?php
    $pass = array();
    $index =0;
    $result = mysqli_query($db, "SELECT * FROM admins");
    while ($row = mysqli_fetch_array($result)) {
        $pass[$index] = $row['password'];
        $newhash = $pass[$index];
        if (password_verify($password, $newhash)) {
            echo "Password Matched";
        } else {
        }
    }
?>

编辑:有人指出要添加用户 ID,但我最初的问题是我验证数据的方式是最好的方式还是有优化的方式?

【问题讨论】:

  • 先选择用户。 SELECT * FROM admins where email = ? 或者您确定管理员。您还应该选择该列,而不是 *
  • 您的代码可能会返回多个匹配多个具有相同密码的人。输入WHERE 以匹配用户名。¨
  • 您可能应该有一个用户 ID 并明确选择该行(例如 SELECT * FROM admins` WHERE id = ...`),这样您只需检查密码是否匹配 任何人?
  • 戈登,批准编辑时要小心,该编辑更改了代码(可能 OP 有正确的代码(未提及错误),但可能并非总是如此)
  • @chris85 你完全正确,我本能地修复了它,甚至没有考虑它。它缺少 1 个大括号。

标签: php mysql mysqli php-5.5


【解决方案1】:

正如克里斯所说,您真的应该只选择包含断言身份的行。虽然两个不同的管理员可能拥有相同的密码,但只要您使用 password_hash() 创建存储的密码,您当前的代码就不可能错误识别用户(因为每个帐户都应该获得一个随机分配的盐)哈希); ccKep 的评论可能是错误的。

这意味着这样的查询:

SELECT password FROM admins WHERE username=?

这消除了在您的 php 代码中遍历结果集中的多行的需要。

如果你还在用户名上添加一个索引,那么它会更快,因为 dbms 要做的工作更少。唯一索引简化了检查重复帐户的问题。

由于散列密码的值取决于盐 - 每行实际上是唯一的,因此无法围绕散列或密码的明文优化查询性能 - 您需要使用断言的身份; Graham 建议基于散列密码进行搜索是错误的。

在实践中,如果网站有任何重要的资产价值,您还应该限制登录率以防止暴力攻击,因此更好的查询应该类似于:

SELECT password
FROM admins
WHERE username=?
AND 5 < (SELECT COUNT(*)
  FROM login_failures
  WHERE client_ip = INET_ATON( ? )
  AND attempt_timestamp > NOW() - INTERVAL 30 MINUTE)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 2019-10-15
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多