PHP:匹配哈希密码,用户输入无效

时间:2015-06-24 05:55:39

标签: php mysql hash passwords

我是PHP的新手,我正在尝试检查用户(登录页面)提供的密码是否与存储在db中的哈希密码相匹配。 数据库中的密码经过$pw = password_hash($_POST["pw"], PASSWORD_BCRYPT);的散列(与我用于用户输入的方法相同),并存储在VARCHAR(255)列中。

我现在尝试使用password_verify将其与用户输入进行比较,但是得到了由else部分引起的以下错误。

有人能告诉我这里做错了什么吗? 我也尝试删除“== true”,但这也不起作用。

我的PHP:

$email = $_POST["email"];
$pw = password_hash($_POST["pw"], PASSWORD_BCRYPT); 

$stmt = $conn->prepare("SELECT email, pw FROM Users WHERE email = ?");
$stmt->bind_param('s', $email);
$stmt->execute();
$result = $stmt->get_result();
if(mysqli_num_rows($result) == 0){
    echo "Email has not been registered yet";
}else{
    if(password_verify($pw, $result["pw"]) == true){
        echo "Password correct";
    }else{
        echo "Password incorrect";
    }   
};

错误:

"Fatal error: Cannot use object of type mysqli_result as array..."

更新
对我而言,这与另一个被称为可能重复的问题不同,因为在我的情况下,我得到上述错误或(当遵循Bing的方法时),结果总是“密码不正确” - 独立于输入。

非常感谢提前。

4 个答案:

答案 0 :(得分:2)

您的代码存在两个问题。

第一个是错误消息中的解释。将结果作为对象返回,而不是数组。您应该将这些值作为对象访问:

var query = new { query = new { term = new { Name = "banana" } } };

第二个问题是您的$result->pw 功能。 $ pw包含用户输入密码的哈希值。因此,当您执行password_verify()时,实际上是根据数据库中的哈希检查密码的哈希值。您应该根据数据库中的哈希检查用户提供的原始密码

答案 1 :(得分:1)

您的$result变量包含mysqli_result个对象,不是您想要的数组。查看文档中的返回值部分,此处为:http://php.net/manual/en/mysqli.query.php

要转换它,只需调用mysqli_fetch_array(以mysqli_result作为参数)并构建结果。以下是您的代码的样子:

$result_object = $stmt->get_result();
$result_array = array();
while($result_item = mysqli_fetch_array($result_object)) {
    array_push($result_array, $result_item);
}

if(count($result_array) == 0){
    echo "Email has not been registered yet";
}else{
    $single_entry = array_pop($result_array);
    if(isset($single_entry["pw"]) && password_verify($single_entry["pw"], $pw)){
        echo "Password correct";
    }else{
        echo "Password incorrect";
    }   
}

几点说明:

  1. 您在最终;
  2. 结尾处不需要}
  3. 您将在$result_array中获得二维数组,这就是我添加array_pop()的原因,假设您只有一封电子邮件记录。
  4. 您的password_verify()来电时参数输入错误,您会发现我已将其切换。
  5. 我做了 NOT 测试,但是它应该让你顺利。

答案 2 :(得分:1)

你实际上做了两件事。

验证哈希 请注意,password_hash()返回算法,cost和salt作为返回哈希的一部分。因此,验证散列所需的所有信息都包含在其中。这允许验证功能验证散列,而无需为盐或算法信息单独存储。 ..from php.net

从数据库中检索密码 mysqli_num_rows函数不会返回密码哈希。尝试fetch此专栏。

但是您正在使用准备语句,因此您必须像显示here那样执行此操作。所以你会做类似的事情:

//Remove
$pw = password_hash($_POST["pw"], PASSWORD_BCRYPT); 
$result = $stmt->get_result();

//Add
$stmt->bind_result($pw);
$stmt->fetch();

//Replace
if(mysqli_num_rows($result) == 0){
...
if(password_verify($pw, $result["pw"]) == true){
//With
if(empty($pw)){
...
if(password_verify($_POST["pw"], $pw) == true){

答案 3 :(得分:1)

我查看了目前为止提供的所有答案,但要么无法让他们完全工作,要么无法让他们返回正确的结果。

由于我是PHP的新手,这可能是由于我对提供的评论的某些部分缺乏了解而我为此道歉但我找到了一个适合我的解决方案。

我确信这不是一个完美的方法,我很乐意根据收到的反馈和建议进一步改进 - 一开始,我需要运行一些东西是非常重要的处理依赖于此的其他部分。

这是我到目前为止的(工作)解决方案:

$email = $_POST["email"];
$pw = $_POST["pw"]; 

$stmt = $conn->prepare("SELECT email FROM Users WHERE email = ?");
$stmt->bind_param('s', $email);
$stmt->execute();
$result = $stmt->get_result();
if(mysqli_num_rows($result) == 0){
    echo "Email has not been registered yet";
}else{
    $stmt = $conn->prepare("SELECT pw FROM Users WHERE email = ? LIMIT 1");
    $stmt->bind_param('s', $email);
    $stmt->execute();
    $result = $stmt->get_result();
    $pwHashed = $result->fetch_assoc();
    if(password_verify($pw, $pwHashed["pw"])){
        echo "Password correct";
    }else{
        echo "Password incorrect";
    }   
}