从数据库中有效地检查哈希密码

时间:2015-06-04 12:00:39

标签: php mysql hash php-password-hash

首先,我已尽力为此找到明确的答案。其次,我的代码似乎有效,但我想确认我是以有效的方式做到这一点,而不是让自己对安全漏洞持开放态度。

首先,我在将用户添加到admin表时使用PHP password_hash;

$stmt = $dbh->prepare("INSERT INTO admin (username, password) VALUES (:username, :password)");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);

$password = password_hash('password', PASSWORD_DEFAULT);

其次,当用户尝试登录时,我只通过匹配用户名从admin表中检索用户,因为我在查询期间看不到检查哈希的方法(这是我不确定的部分是否存在是一种更好的方法),还可以从POST输入中定义$ password变量;

$stmt = $dbh->prepare("SELECT * FROM admin WHERE username = :username");
    $stmt->bindParam(':username', $username);
    $username = $_POST['username'];
    // define $password for use in password verify
    $password = $_POST['password'];

第三,如果查询有结果,我在用户输入上运行password_verify以检查匹配,然后根据true或false分支。

if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            if (password_verify($password, $row['password'])) {
                session_start();
                foreach ($row as $user) {
                    $_SESSION['user'] = $row['id'];
                }
            } else {
                $errors = true;
            }                       
            header('location: leads.php');
        }
        else {
            $errors = true;
        }

我知道有许多不同的方法来散列/保护密码,但使用原生的password_hash函数是我决定采用的方式,我的问题是我做得对吗/有更好的方法吗?

提前致谢。

1 个答案:

答案 0 :(得分:0)

基本上,除了已经提到的内容之外,你的代码看起来还不错。当你要求改进,特别是与性能相关的改进时,我们在这里:

  • username
  • 上添加索引
  • 如果您的表获得了大量条目,请从username中删除索引,添加一个名为hash的新列,并添加索引并重写您的插入并选择如下:

    INSERT INTO admin (username, password, hash) VALUES (:username, :password, crc32(username))

    SELECT * FROM admin WHERE username = :username AND hash=crc32(:username)

我假设您使用MySQL,因此在查询中添加LIMIT 1有助于优化器并在找到行后停止搜索。

如果你只使用一行,也可以避免foreach - 循环。

BTW:header('location: leads.php');应该读取header('Location: leads.php');并使用绝对路径使事情更加健壮。