php - 无法从用户表(MySql)中选择用户名和密码列

标签 php mysql

我正在本地服务器上建立一个身份验证系统,以使用 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_hashpassword_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/

相关文章:

php - 如何防止 PHP 中的 SQL 注入(inject)?

php - 如何找到丢失的索引?

php - 这个 MySQL 查询有问题吗?

C# 如何将 Datagridview 中的多行保存到一个数据库

php - "SQLSTATE[HY000]: General error"- 一条语句中的多个 SQL 查询

php - 将 php 字符串转换为标题大小写

php - 循环中的 Eloquent 关系

mysql - 仅获取另一个表中(至多)1 列值的行

php - 代码示例,我可以写什么打动雇主?

父框架的 PHP header 位置更改