PHP:将哈希密码与用户输入匹配不起作用

PHP:将哈希密码与用户输入匹配不起作用,php,mysql,hash,passwords,Php,Mysql,Hash,Passwords,我是PHP新手,正在尝试检查用户提供的密码(登录页面)是否与数据库中存储的哈希密码匹配。 数据库中的密码通过$pw=password\u散列($\u POST[“pw”],password\u BCRYPT)散列(与我用于用户输入的方法相同)并存储在VARCHAR(255)列中 我现在尝试使用password\u verify将其与用户输入进行比较,但得到以下错误,这是由else部分引起的 有人能告诉我我做错了什么吗? 我也尝试过删除“==true”,但也没有成功 我的PHP: $email =

我是PHP新手,正在尝试检查用户提供的密码(登录页面)是否与数据库中存储的哈希密码匹配。 数据库中的密码通过
$pw=password\u散列($\u POST[“pw”],password\u BCRYPT)散列
(与我用于用户输入的方法相同)并存储在
VARCHAR(255)
列中

我现在尝试使用password\u 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..."
$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";
    }   
}
更新:
对我来说,这与另一个被称为可能重复的问题不同,因为在我的情况下,我要么得到上述错误,要么(当遵循Bing下面的方法时)结果总是“密码不正确”——与输入无关


非常感谢

您的代码有两个问题

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

$result->pw

第二个问题是您的
密码\u verify()
函数$pw包含用户输入密码的散列。因此,当您执行
password\u veryify()
时,您实际上是在数据库中检查密码的哈希值。您应该根据数据库中的哈希值检查用户提供的原始密码

您的
$result
变量包含
mysqli_result
对象,而不是预期的数组。查看文档中的“返回值”部分,如下所示:

要转换它,只需调用(将
mysqli\u结果作为参数)并构建结果。下面是您的代码的外观:

$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";
    }   
}
几点注意:

  • 您不需要
    在期末考试结束时
    }
  • 您将在
    $result\u array
    中获得一个二维数组,这就是我添加
    数组\u pop()
    的原因,假设您只有一条电子邮件记录
  • 您的
    密码\u verify()
    调用中的参数顺序错误,您会注意到我切换了它们
  • 我做了而不是测试,但它会让你在路上顺利

  • 你实际上做错了两件事

    验证哈希值 请注意,password_hash()返回算法、成本和盐,作为返回哈希的一部分。因此,验证哈希所需的所有信息都包含在其中。这允许verify函数验证散列,而不需要单独存储salt或算法信息。

    从数据库检索密码 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新手,这可能是因为我对所提供评论的某些部分缺乏理解,对此我深表歉意,但我找到了一个适合我的解决方案

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

    以下是我迄今为止的(有效)解决方案:

    "Fatal error: Cannot use object of type mysqli_result as array..."
    
    $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";
        }   
    }
    

    print\r($result)
    转储您的结果,它是对象,可以通过
    $result->pw
    $pw
    检索它,其中包含用户输入密码的散列。因此,当您执行
    password\u veryify()
    时,您实际上是在数据库中检查密码的哈希值。您应该根据数据库中的哈希值检查用户提供的原始密码。PHP错误的第一条规则:使用Google搜索错误消息。@Jeemusu错误与
    password\u hash()
    无关,与
    mysqli
    有关。没错,Hobo,但一旦解决了这个问题,您就会注意到
    密码验证()
    实际上有一个问题。也谢谢您。最后一个问题是:我需要这里的“==true”吗?在php.net上,他们似乎忽略了这一点。很高兴能提供帮助。注意注2。理解多维数组很重要。更好的阅读:是的,你可以在任何地方省略
    ==true
    。请注意,这是两个
    =
    符号。三是不同的问题:不,你不需要
    }
    后的code>。
    }
    就像结束一个段落,然后添加
    就像一个额外的句号。Switch语句可能需要
    中断(以
    结尾)在两个案例之间(因此它们并非都按顺序运行,从第一个匹配开始),但这是一个单独的操作。让我们来看看。谢谢!你能解释一下我应该做些什么来涵盖你答案的第二部分吗?@TaneMahuta$conn里面是什么?你在使用mysqli还是pdo?根据您使用的内容,我可以给出更详细的答案。谢谢-我使用mysqli:$conn=newmysqli($dbServer,$dbUser,$dbPass,$dbName);$conn->set_字符集(“utf8”);这里要补充一点:这个问题还没有解决。我正在尝试这里发布的另一种方法,但这并没有检测到密码是否正确。@TaneMahuta更新了我的答案检查,如果这对你有效。