密码未使用password_verify功能验证

时间:2016-02-02 06:06:21

标签: php mysql database mysqli passwords

我想我直接从mysql数据库使用函数PASSWORD散列密码(我在这里做错了吗?)。我正在尝试使用此代码验证密码:

    if($submit)
    {
        $first=$_POST['first'];
        $password=$_POST['password'];
        $hash="*85955899FF0A8CDC2CC36745267ABA38EAD1D28"; //this is the hashed password i got by using function PASSWORD in database
        $password=password_verify($password,$hash);
        $db = new mysqli("localhost", "root","","learndb");
        $sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";
        $result = $db->query($sql);
        $result=mysqli_num_rows($result);


        if($result>0)
    {

        session_start();
        $_SESSION['logged_in'] = true;
        session_regenerate_id(true);
        header("Location:loginhome.php");

    }
}

但密码不匹配。我在这里缺少什么?

更新

在完成所有建议之后,我使用了来自php代码的password_hash来存储到数据库中。

$db = new mysqli("localhost", "root","","learndb");
$password=password_hash('ChRisJoRdAn123',PASSWORD_DEFAULT);
$sql="INSERT INTO admin (username,password)values('ChrisJordan','$password')";
$db->query($sql);

密码仍不匹配。

4 个答案:

答案 0 :(得分:2)

无法在数据库中搜索salted密码哈希。要计算哈希值,您需要使用password_hash()函数,就像在insert语句中已正确执行一样。

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);

要检查密码,首先需要按用户名搜索(使用准备好的查询来避免sql注入):

$sql = 'select * from admin where username = ?';
$db->prepare($sql);
$db->bind_param('s', $first);

当您最终从数据库中获取存储的哈希时,可以像这样检查:

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

答案 1 :(得分:2)

评论太长了。

看到此问题尚未在任何答案旁边包含绿色勾号,我提交以下内容以指出可能的问题。

我注意到您正试图从MD5迁移到password_hash() - password_verify()

您需要知道的是,MD5产生的是32个字符长度的字符串,而password_hash()的长度为60个字符串。

  • 使用varchar(255)

如果您将密码列的长度保持为32,那么您需要清除该列中的现有哈希值,然后按照手册建议的那样将列更改为60或255。

您需要清除所有现有密码,更改列,创建新哈希,然后再次尝试登录代码。

我在你的代码中看到了这一点:

"*85955899FF0A8CDC2CC36745267ABA38EAD1D28"; //this is the hashed password i got by using function PASSWORD in database

此字符串*85955899FF0A8CDC2CC36745267ABA38EAD1D28长40,太短而且已被切断。

这告诉我你的列的长度是40,而不是60,或者如手册所示,再次为255。

MD5参考:

  

将哈希值作为32个字符的十六进制数返回。

password_hash()的参考:

  

结果将始终为60个字符的字符串,或者在失败时为FALSE。

要更改列,请参阅以下链接:

还要确保您的表单包含POST方法,并且输入具有匹配的名称属性,并且不会引入任何空格。

您可以使用trim()来摆脱这些。

error reporting添加到文件的顶部,这有助于查找错误。

<?php 
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Then the rest of your code

旁注:只应在暂存时进行显示错误,而不是生产。

以及or die(mysqli_error($db))mysqli_query()

修改:

你需要做的是获取一个数组并获得匹配。

$sql = "select * from admin where username = '".$first."' and password = '".$password."' ";
$result = $db->query($sql);

if ($result->num_rows === 1) {
     $row = $result->fetch_array(MYSQLI_ASSOC);
        if (password_verify($password, $row['password'])) {
            //Password matches, so create the session
            // $_SESSION['user']['user_id'] = $row['user_id'];
            // header("Location:/members");

        echo "Match";


        }else{
            echo  "The username or password do not match";
        }
}

另一种可能的解决方案:

$query = "SELECT * from admin WHERE username='$first'";

$result = $db->query($query);

if($result->num_rows ===1){
$row = $result->fetch_array(MYSQLI_ASSOC);

if (password_verify($password, $row['password'])){

    echo "match";
} else {
$error = "email or Password is invalid";
echo $error;
}

}
mysqli_close($db); // Closing Connection

答案 2 :(得分:1)

您必须使用password_hash对使用password_verify验证的密码进行编码。

MySQL函数PASSWORD完全不同。它用于编码特定于MySQL身份验证的密码。 (MySQL明确建议不要使用PASSWORD进行其他而不是MySQL身份验证。)

两者使用不同的散列算法,以不同的格式显示其输出,并且通常彼此不兼容。

<小时/> 使用password_hashpassword_verify的典型方法是:

$hash = password_hash($password, PASSWORD_DEFAULT);
//Store $hash in your database as the user's password

//To verify:
//Retrieve $hash from the database, given a username
$valid = password_validate($password, $hash);

您的代码中的问题是您正在执行此操作:

$password=password_verify($password,$hash);
$sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";

password_verify返回一个布尔值(密码和散列匹配)。相反,您需要从数据库中检索哈希值,并将输入的密码与该哈希值匹配。

答案 3 :(得分:1)

password_verify是一个布尔函数,返回truefalse。在您的代码中,从Post param获取密码值后,您执行此操作

$password=password_verify($password,$hash);

$password值更改为truefalse,并将您在mysql select语句中使用的$password中存储的布尔值

$sql = "select * from admin where username = '" . $first . "' and password = '". $password . "'";

另一件事:您使用的散列/加密密码可能不是您正在使用的密码的正确哈希值。

更新:试试这个

$cost = [
    'cost' => 15,
];

$hash_password = password_hash('ChRisJoRdAn123', PASSWORD_BCRYPT, $cost);

在任何数据库操作之前,将password字段varchar长度更改为&gt; = 64

$sql = "INSERT INTO admin (username,password)values('ChrisJordan','".$hash_password."')";

插入操作后,使用用户

执行select语句
$sql = "select * from admin where username = 'ChrisJordan'";

post参数获取hased passwordpassword后,您需要使用password_verify验证这两个密码

if (password_verify(validate($_POST['password']), $hash_password_from_db)) {
    echo "Valid Password";
}else{
    echo "Invalid Password";    
}