首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >password_hash,password_verify,MySQL误解?

password_hash,password_verify,MySQL误解?
EN

Stack Overflow用户
提问于 2014-01-12 09:14:08
回答 4查看 14.1K关注 0票数 5

我已经更新了代码,但脚本仍然返回“Fail”。消息。我一定是漏掉了什么,我听取了大家的意见。要不然我就是个笨蛋,哈哈!下面是更新后的代码:

代码语言:javascript
复制
require('../connect.php');
$username = $_POST['username-sign-in'];
$password = $_POST['password-sign-in'];
if true then exit() for {
    empty($username);
    empty($password);
}
if (isset($username, $password)) {
    $getuser = $connection->prepare('SELECT `username`, `password`
                       FROM `users` WHERE `username` = ?');
    $getuser->bind_param('s', $username);
    $getuser->execute();
    $userdata = $getuser->get_result();
    $row = $userdata->fetch_array(MYSQLI_ASSOC);
    echo 'Password from form: ' . $password . '<br />';
    echo 'Password from DB: ' . $row['password'] . '<br />';
    if (password_verify($password, $row['password'])) {
        echo 'Success.';
        exit();
    }
    else {
        echo 'Fail.';
        exit();
    }
}
else {
    echo 'Please enter your username and password.';
    $connection->close();
    exit();
}

signup.php

代码语言:javascript
复制
require('../connect.php');
$ip = $_SERVER['REMOTE_ADDR'];
$username = $_POST['username-sign-up'];
$password = $_POST['password-sign-up'];
$hashedpassword = password_hash($_POST['password-sign-up'], 
                       PASSWORD_BCRYPT, ['cost' => 12]);
$email = strtolower($_POST['email-sign-up']);
if true then exit() for {
    empty($username)
    empty($password)
    empty($email)
    !filter_var($email, FILTER_VALIDATE_EMAIL)
    strlen($username) < 2 || strlen($username) > 32
    strlen($password) < 6 || strlen($password) > 32
}
$usernameandemailcheck = $connection->prepare('SELECT `username`, `email` 
                       FROM `users` WHERE `username` = ? AND `email` = ?');
$usernameandemailcheck->bind_param('ss', $username, $email);
$usernameandemailcheck->execute();
$result = $usernameandemailcheck->get_result();
$row = $result->fetch_array(MYSQLI_ASSOC);
// .. Username and email validation
if (isset($username, $hashedpassword, $email)) {
    // Create and send mail
    $query = $connection->prepare('INSERT INTO users (`ip`, `username`, 
                       `password`, `email`) VALUES (?, ?, ?, ?)');
    $query->bind_param('ssss', $ip, $username, $hashedpassword, $email);
    $query->execute();
    // SUCCESS
}
else {
    // FAILURE
}
EN

回答 4

Stack Overflow用户

发布于 2014-01-12 09:26:17

您不能对输入进行散列,然后在数据库中对其进行查询,因为散列每次都会使用不同的随机盐。所以你可以将同一个密码散列一千次,得到1000个不同的结果。

您只需在数据库中查询与用户名相关的记录,然后使用password_verify()将从数据库返回的密码散列与输入的密码进行比较。

此外,最初在创建密码时将散列写入数据库(使用password_hash())时,不需要对散列进行转义。在密码验证过程中根本不使用password_hash()

票数 23
EN

Stack Overflow用户

发布于 2014-01-12 09:27:58

快速浏览一下这些函数,就会发现你可能把测试搞错了。

您应该将密码的散列版本存储在数据库中,然后将其与通过$_POST提供的密码进行比较。然后剩下的就会像..。

代码语言:javascript
复制
$getuser = $connection->prepare('SELECT `password` 
                                        FROM `users` WHERE `username` = ?');
$getuser->bind_param('s', $username);
$getuser->execute();
$userdata = $getuser->get_result();
$row = $userdata->fetch_array(MYSQLI_ASSOC);
echo 'Password from form: ' . $hashedpassword . '<br />';
echo 'Password from DB: ' . $row['password'] . '<br />';
if (password_verify($password, $row['password'])) {
    // $password being $_POST['password-sign-in']
    // $row['password'] being the hashed password saved in the database
    echo 'Success.';
    exit();
} else {
    echo 'Fail.';
    exit();
}
票数 10
EN

Stack Overflow用户

发布于 2014-01-12 09:21:43

您是否尝试过像'那样更改单引号

代码语言:javascript
复制
$getuser = $connection->prepare('SELECT `username`, `password` FROM `users` WHERE `username` = ? AND `password` = ?');
$getuser->bind_param('ss', $username, $hashedpassword);

要使用双引号,如"

代码语言:javascript
复制
$getuser = $connection->prepare("SELECT `username`, `password` FROM `users` WHERE `username` = ? AND `password` = ?");
$getuser->bind_param("ss", $username, $hashedpassword);

另外,为什么要与password相匹配?也许这将适用于您的测试用例:

代码语言:javascript
复制
$getuser = $connection->prepare("SELECT `username`, `password` FROM `users` WHERE `username` = ?");
$getuser->bind_param("s", $username);

编辑此外,当您执行检查时,您实际上是在对密码进行双重散列:

代码语言:javascript
复制
if (password_verify($row['password'], $hashedpassword)) {

只需执行以下操作:

代码语言:javascript
复制
if (password_verify($password, $row['password'])) {

问题是password_verify的语法是:

代码语言:javascript
复制
boolean password_verify ( string $password , string $hash )

您需要在第一个参数中发送明文/非散列密码,然后将散列值放入第二个参数中。试一试。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21070107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档