如何使密码验证函数与$\u post一起工作

sr4lhrrt  于 2021-06-23  发布在  Mysql
关注(0)|答案(2)|浏览(320)

我想用密码验证登录系统。我已经用默认密码加密了我的密码。我还将散列存储在数据库中。现在我想使用passwordverify来创建一个登录系统,但是函数总是返回一个值true。有人能解释为什么吗?有人能给我解释一下如何用$\u post验证密码吗?
哈希的代码

<?php
/**
 * Created by PhpStorm.
 * User: jbosma
 * Date: 24/07/2018
 * Time: 23:21
 */
include_once "dbconnection.php";
if (isset($_POST["submit"])) { // send the input
    $username = $_POST["username"]; // post the input username
    $password = $_POST["password"]; // post the input password
    $conn = new PDO("mysql:host=localhost;dbname=loginapp", $user, $pass); // database connection
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // error mode
    $hash = PASSWORD_HASH($password, PASSWORD_DEFAULT); // make $hash so you can give that to your password in the query
    $sql = "INSERT INTO users (username, password) VALUES ('".$username."','".$hash."')"; // insert the username and the password that will be hashed
    $conn->exec($sql); // excecute the query above
    header('location: register.php'); // after you submit it redirects to login.php

}

密码验证代码

<?php
/**
 * Created by PhpStorm.
 * User: jbosma
 * Date: 27/07/2018
 * Time: 12:11
 */
include_once "dbconnection.php";
if (isset($_POST["submit"])) { // send the input
    $username = $_POST["username"]; // post the input username
    $password = $_POST["password"]; // post the input password

    $hash = $password; // hash from password
    if (password_verify($_POST["password"], $hash)) {
        echo "Welcome";
    } else {
        echo "Wrong Password";
    }
}
?>
hof1towb

hof1towb1#

在您的reg表单中有这样的内容,它在这个示例中使用bcrypt。这只是显示密码\u散列函数
登记

// Other code  leading up to this..
....
//
$passHash = password_hash($pass, PASSWORD_BCRYPT, array("cost" => 12));

  $insrt = "INSERT INTO users (username, password) VALUES (:username, :password)";
  $stmt = $pdo->prepare($insrt);

  $stmt->bindValue(':username', $username);
  $stmt->bindValue(':password', $passHash);

  $result = $stmt->execute();

  if($result){
// Do whatever you want

登录

// Other code  leading up to this..
....
//
$validPassword = password_verify($pass, $user['password']);

    if($validPassword){

        $_SESSION['user_id'] = $user['username'];
        $_SESSION['logged_in'] = time();

        // redirects in this case
        header( "Location: /wherever.php" );
        die();

    } else{
        die('Wrong password!');
    }

这只是展示如何使用函数本身,应用这个原则,你应该很好去

kxkpmulp

kxkpmulp2#

问题
你的 password_verify 始终返回 true 因为,通过使用 password_verify($_POST["password"], $hash) ,你实际上是在比较 $_POST["password"]$hash = $password 以及 $password = $_POST["password"] .
解决方案
这个 password_verify 应该比较发布的密码( $_POST["password"] )首先,必须从数据库中提取密码散列。因此,您的登录代码应该如下所示:

<?php
include_once "dbconnection.php";

if (isset($_POST["submit"])) {
    $username = $_POST["username"];
    $password = $_POST["password"];

    $sql = "SELECT password FROM users where username = '" . $username . "' LIMIT 1";
    $statement = $conn->query($sql);
    $credentials = $statement->fetch(PDO::FETCH_ASSOC);

    if ($credentials) { // Record found.
        $hash = $credentials['password'];

        // Compare the posted password with the password hash fetched from db.
        if (password_verify($password, $hash)) {
            echo "Welcome";
        } else {
            echo "Wrong Password";
        }
    } else {
        echo 'No credentials found for the given user.';
    }
}

请注意,此解决方案对sql注入开放。改用准备好的语句(参见下面的扩展示例)。
另一个扩展示例:
下面是另一个使用 password_hash - password_verify 串联。尽管我同意@tadman:您应该使用外部库(作为您所希望的框架的一部分提供,或者作为独立组件提供)来提供一个可靠的安全层。
注意,避免所谓的sql注入,更具体地说,确保安全的身份验证/授权系统的第一个重要步骤是使用准备好的语句。在使用数据访问层时,请尝试始终应用此准备步骤。
单文件

<?php
require 'connection.php';

// Signalize if a new account could be created, or not.
$accountCreated = FALSE;

/*
 * ================================
 * Operations upon form submission.
 * ================================
 */
if (isset($_POST['submit'])) {
    /*
     * =======================
     * Read the posted values.
     * =======================
     */
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';

    /*
     * ===========================
     * Validate the posted values.
     * ===========================
     */
    // Validate the username.
    if (empty($username)) {
        $errors[] = 'Please provide a username.';
    } /* Other validations here using elseif statements */

    // Validate the password.
    if (empty($password)) {
        $errors[] = 'Please provide a password.';
    } /* Other validations here using elseif statements */

    /*
     * ==================================
     * Check if user exists. Save if not.
     * ==================================
     */
    if (!isset($errors)) {
        /*
         * =============================
         * Check if user already exists.
         * =============================
         */

        /*
         * The SQL statement to be prepared. Notice the so-called named markers.
         * They will be replaced later with the corresponding values from the
         * bindings array when using PDOStatement::bindValue.
         *
         * When using named markers, the bindings array will be an associative
         * array, with the key names corresponding to the named markers from
         * the sql statement.
         *
         * You can also use question mark markers. In this case, the bindings
         * array will be an indexed array, with keys beginning from 1 (not 0).
         * Each array key corresponds to the position of the marker in the sql
         * statement.
         *
         * @link http://php.net/manual/en/mysqli.prepare.php
         */
        $sql = 'SELECT COUNT(*)
                FROM users
                WHERE username = :username';

        /*
         * The bindings array, mapping the named markers from the sql
         * statement to the corresponding values. It will be directly
         * passed as argument to the PDOStatement::execute method.
         *
         * @link http://php.net/manual/en/pdostatement.execute.php
         */
        $bindings = [
            ':username' => $username,
        ];

        /*
         * Prepare the sql statement for execution and return a statement object.
         *
         * @link http://php.net/manual/en/pdo.prepare.php
         */
        $statement = $connection->prepare($sql);

        /*
         * Execute the prepared statement. Because the bindings array
         * is directly passed as argument, there is no need to use any
         * binding method for each sql statement's marker (like
         * PDOStatement::bindParam or PDOStatement::bindValue).
         *
         * @link http://php.net/manual/en/pdostatement.execute.php
         */
        $statement->execute($bindings);

        /*
         * Fetch the data and save it into a variable.
         *
         * @link https://secure.php.net/manual/en/pdostatement.fetchcolumn.php
         */
        $numberOfFoundUsers = $statement->fetchColumn(0);

        if ($numberOfFoundUsers > 0) {
            $errors[] = 'The given username already exists. Please choose another one.';
        } else {
            /*
             * ========================
             * Save a new user account.
             * ========================
             */
            // Create a password hash.
            $passwordHash = password_hash($password, PASSWORD_BCRYPT);

            $sql = 'INSERT INTO users (
                        username,
                        password
                    ) VALUES (
                        :username,
                        :password
                    )';

            $bindings = [
                ':username' => $username,
                ':password' => $passwordHash,
            ];

            $statement = $connection->prepare($sql);
            $statement->execute($bindings);

            // Signalize that a new account was successfully created.
            $accountCreated = TRUE;

            // Reset all values so that they are not shown in the form anymore.
            $username = $password = NULL;
        }
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo - Register</title>

        <style type="text/css">
            .messages { margin-bottom: 10px; }
            .messages a { text-transform: uppercase; font-weight: 700;}
            .error, .success { margin-bottom: 5px; }
            .error { color: #ff0000; }
            .success { color: #32cd32; }
            .form-group { margin-bottom: 10px; }
            .form-group label { display: inline-block; min-width: 90px; }
        </style>
    </head>
    <body>

        <h3>
            Register
        </h3>

        <div class="messages">
            <?php
            if (isset($errors)) {
                foreach ($errors as $error) {
                    ?>
                    <div class="error">
                        <?php echo $error; ?>
                    </div>
                    <?php
                }
            } elseif ($accountCreated) {
                ?>
                <div class="success">
                    You have successfully created your account.
                    <br/>Would you like to <a href="login.php">login</a> now?
                </div>
                <?php
            }
            ?>
        </div>

        <form action="" method="post">

            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" id="username" name="username" value="<?php echo $username ?? ''; ?>" placeholder="Username">
            </div>

            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" id="password" name="password" value="<?php echo $password ?? ''; ?>" placeholder="Password">
            </div>

            <button type="submit" id="registerButton" name="submit" value="register">
                Register
            </button>
        </form>

    </body>
</html>

登录.php

<?php
require 'connection.php';

/*
 * ================================
 * Operations upon form submission.
 * ================================
 */
if (isset($_POST['submit'])) {
    /*
     * =======================
     * Read the posted values.
     * =======================
     */
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';

    /*
     * ===========================
     * Validate the posted values.
     * ===========================
     */
    // Validate the username.
    if (empty($username)) {
        $errors[] = 'Please provide a username.';
    } /* Other validations here using elseif statements */

    // Validate the password.
    if (empty($password)) {
        $errors[] = 'Please provide a password.';
    } /* Other validations here using elseif statements */

    /*
     * ======================
     * Check the credentials.
     * ======================
     */
    if (!isset($errors)) { // No errors yet.
        $sql = 'SELECT username, password
                FROM users
                WHERE username = :username
                LIMIT 1';

        $statement = $connection->prepare($sql);

        $statement->execute([
            ':username' => $username,
        ]);

        /*
         * Fetch the credentials into an associative array.
         * If no record is found, the operation returns FALSE.
         */
        $credentials = $statement->fetch(PDO::FETCH_ASSOC);

        if ($credentials) { // Record found.
            $fetchedUsername = $credentials['username'];
            $fetchedPasswordHash = $credentials['password'];

            /*
             * Compare the posted username with the one saved in db and the posted
             * password with the password hash saved in db using password_hash.
             *
             * @link https://secure.php.net/manual/en/function.password-verify.php
             * @link https://secure.php.net/manual/en/function.password-hash.php
             */
            if (
                    $username === $fetchedUsername &&
                    password_verify($password, $fetchedPasswordHash)
            ) {
                header('Location: welcome.html');
                exit();
            } else {
                $errors[] = 'Invalid credentials. Please try again.';
            }
        } else {
            $errors[] = 'No credentials found for the given user.';
        }
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo - Login</title>

        <script type="text/javascript">
            function validateForm() {
                // ...Some form validation, if needed...
                return true;
            }
        </script>

        <style type="text/css">
            .messages { margin-bottom: 10px; }
            .error { margin-bottom: 5px; color: #ff0000; }
            .form-group { margin-bottom: 10px; }
            .form-group label { display: inline-block; min-width: 90px; }
        </style>
    </head>
    <body>

        <h3>
            Login
        </h3>

        <div class="messages">
            <?php
            if (isset($errors)) {
                foreach ($errors as $error) {
                    ?>
                    <div class="error">
                        <?php echo $error; ?>
                    </div>
                    <?php
                }
            }
            ?>
        </div>

        <form action="" method="post" onsubmit="return validateForm();">

            <div class="form-group">
                <label for="username">Username</label>
                <input type="text" id="username" name="username" value="<?php echo $username ?? ''; ?>" placeholder="Username">
            </div>

            <div class="form-group">
                <label for="password">Password</label>
                <input type="password" id="password" name="password" value="<?php echo $password ?? ''; ?>" placeholder="Password">
            </div>

            <button type="submit" id="loginButton" name="submit" value="login">
                Login
            </button>
        </form>

    </body>
</html>

连接.php

<?php

/*
 * This page contains the code for creating a PDO connection instance.
 */

// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'tests');
define('USERNAME', 'root');
define('PASSWORD', 'root');
define('CHARSET', 'utf8');

$connection = new PDO(
        sprintf('mysql:host=%s;port=%s;dbname=%s;charset=%s', HOST, PORT, DATABASE, CHARSET)
        , USERNAME
        , PASSWORD
        , [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => FALSE,
    PDO::ATTR_PERSISTENT => FALSE,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]
);

欢迎.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo - Welcome</title>
    </head>
    <body>

        <h3>
            Welcome
        </h3>

        <div>
            Hi. You are now logged-in.
        </div>

    </body>
</html>

表定义
请注意 password 列。这个领域应该(至少)这么长。更多详细信息请参见密码散列(在“说明”中)。

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

相关问题