我正在本地服务器上建立一个身份验证系统,以使用 PHP 和 MYSQL 测试运行一些供我个人使用的脚本。我运行以下代码从“用户”表中选择“用户名”和“密码”列,但在输入正确的凭据后我不会收到此错误:
Invalid username/password combination
这是脚本:
<?php // authentication.php
require_once 'login.php';
$connection = new mysqli($hn, $un, $pw, $db);
if ($connection->connect_error) die($connection->connect_error);
if (isset($_SERVER['PHP_AUTH_USER']) &&
isset($_SERVER['PHP_AUTH_PW'])) {
$un_temp = mysql_entities_fix_string($connection, $_SERVER['PHP_AUTH_USER']);
$pw_temp = mysql_entities_fix_string($connection, $_SERVER['PHP_AUTH_PW']);
$query = "SELECT * FROM users WHERE username='$un_temp' AND password='$pw_temp'";
$result = $connection->query($query);
if (!$result) die($connection->error);
else if ($result->num_rows) {
$row = $result->fetch_array(MYSQLI_NUM);
$result->close();
if ( password_verify( $pw_temp == $row[3]) ) {
echo "$row[0] $row[1] : Hi $row[0], you are now logged in as '$row[2]'";
}
}
else die("Invalid username/password combination");
} else {
header('WWW-Authenticate: Basic realm="Restricted Section"');
header('HTTP/1.0 401 Unauthorized');
die("Pleaser enter your username and password");
}
$connection->close();
function mysql_entities_fix_string($connection, $string) {
return htmlentities(mysql_fix_string($connection, $string));
}
function mysql_fix_string($connection, $string) {
if (get_magic_quotes_gpc()) $string = stripslashes($string);
return $connection->real_escape_string($string);
}
?>
最佳答案
password_verify
接受提交的密码及其关联的密码哈希,但提供的是 bool 值 ($pw_temp == $row[3]
) 请参阅: http://php.net/manual/en/function.password-verify.php 。
假设您使用不带静态盐的password_hash
来将值保存在数据库中。无法查询密码列,因为 password_hash
会自动使用唯一值对密码进行加盐处理。这会阻止您将提交值的第二个哈希值与数据库中的哈希值进行比较。因此,您需要将用户名存储为唯一索引,或者迭代重复的用户名,然后调用 password_verify
来比较每个用户的密码。
假设用户名在您的表中是唯一的,您应该将代码更新为如下所示。
if (!isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
header('WWW-Authenticate: Basic realm="Restricted Section"');
header('HTTP/1.0 401 Unauthorized');
die("Please enter your username and password");
}
$un_temp = mysql_entities_fix_string($connection, $_SERVER['PHP_AUTH_USER']);
$pw_temp = mysql_entities_fix_string($connection, $_SERVER['PHP_AUTH_PW']);
$query = "SELECT * FROM `users` WHERE `username`='$un_temp'";
if (!$result = $connection->query($query)) {
die($connection->error);
}
if (!$result->num_rows) {
die("Invalid username/password combination");
}
$row = $result->fetch_array(MYSQLI_NUM);
$result->close();
if (password_verify($pw_temp, $row[3])) {
echo "$row[0] $row[1] : Hi $row[0], you are now logged in as '$row[2]'";
}
$connection->close();
Demonstration 请注意每个散列密码有何不同。 请记住,由于我无法查询数据库,因此我使用数组来显示等效过程。
<小时/>您的原始代码中还有一些与语法相关的问题,在评论中需要注意一下。
else if
应该是一个单词,这样它看起来像 elseif
[sic] 以避免语法冲突,但由于您的条件会导致调用 die()
,不需要 else
。
isset
可以验证多个参数,因此如果不需要与 &&
比较,则再次调用它 [sic] 。
使用标识符引号(反引号)包裹列名和表名,将有助于避免 MySQL 保留关键字问题 [sic] 。
SELECT * FROM `users` WHERE `username`='$un_temp' AND `password`='$pw_temp'
最后,由于加密算法和成本在 PHP 安全更新 [sic] 之间可能会发生变化。使用 password_hash
和 password_verify
时,您应始终确保密码仍然是加密安全的,方法是使用 password_needs_rehash
[sic],如下所示:
if (password_verify($password, $oldHash)) {
//verify legacy password to new password_hash options
if (password_needs_rehash($oldHash, \PASSWORD_DEFAULT)) {
//rehash/store plain-text password using new hash
$newHash = password_hash($password, \PASSWORD_DEFAULT);
$updateSQL = "UPDATE `users` SET `password`='$newHash' WHERE `username`='$un_temp' AND `password`='$oldHash'";
$connection->query($updateSQL);
}
}
关于php - 无法从用户表(MySql)中选择用户名和密码列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44944396/