PHP:将散列密码与用户输入匹配不起作用



我是PHP新手,正在尝试检查用户(登录页面)提供的密码是否与数据库中存储的哈希密码匹配。数据库中的密码通过$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下面的方法时)结果总是"密码不正确"——与输入无关。

非常感谢。

您的代码有两个问题。

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

$result->pw

第二个问题是关于password_verify()函数$pw包含用户输入密码的散列。因此,当您执行password_veryify()时,实际上是将密码的哈希值与数据库中的哈希值进行比较。您应该根据数据库中的哈希来检查用户提供的原始密码

您的$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. 您将在$result_array中得到一个二维数组,这就是我添加array_pop()的原因,假设您只有一个电子邮件记录
  3. 您的参数与password_verify()调用的顺序不正确,您会注意到我切换了它们
  4. 我做了而不是测试,但它应该会让你顺利前进

您实际上做错了两件事。

验证哈希请注意,password_hash()返回算法、cost和salt作为返回哈希的一部分。因此,验证哈希所需的所有信息都包含在其中。这允许验证函数验证哈希,而不需要单独存储salt或算法信息。..来自php.net

从数据库中检索密码mysqli_num_rows函数不返回密码哈希。尝试获取此列。

但是你使用的是prepare语句,所以你必须像这里显示的那样操作。所以你会做一些类似的事情:

//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){

我浏览了迄今为止提供的所有答案,但要么无法让它们完全发挥作用,要么无法让他们返回正确的结果。

由于我是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";
    }   
}

相关内容

  • 没有找到相关文章

最新更新