我是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";
}
}
几个注意事项:
- 在最后的
}
结束时,您不需要;
- 您将在
$result_array
中得到一个二维数组,这就是我添加array_pop()
的原因,假设您只有一个电子邮件记录 - 您的参数与
password_verify()
调用的顺序不正确,您会注意到我切换了它们 - 我做了而不是测试,但它应该会让你顺利前进
您实际上做错了两件事。
验证哈希请注意,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";
}
}