php - Password_Hash、Mysql、SetFetchMode、Password_verify

标签 php mysql

在我被钉在十字架上之前,我已经研究了一个星期,如果有人能提供帮助,我将不胜感激。我还阅读了该平台上所有关于 password_hashpassword_verify 的文章,但是没有一个解决方案对我有用,从字符串长度和数据库长度等等,所以我决定发布我的问题。

我正在编写一个登录脚本,我使用了password_verify;我刚刚学习了 PHP 的安全性,想改进我的代码。

每次我尝试登录,它都登录不上。

public function create() {

    // Don't forget your SQL syntax and good habits:
    // - INSERT INTO table (key, key) VALUES ('value', 'value')
    // - single-quotes around all values
    // - escape all values to prevent SQL injection
   /* $sql = "INSERT INTO users (username, password, first_name, last_name)
                      VALUES( ?, ?, ?, ?)";*/
    $sql = "INSERT INTO users (username, password, email, date_created)
                      VALUES( :username, :password, :email, :date_created)";
    try {
        // prepare sql and bind parameters
        $core = ConnectionManager::getInstance();
        $stmt = $core->con->prepare($sql);
       /*$stmt = $db->prepare("INSERT INTO users (id, username, password, first_name, last_name)
            VALUES (:id, :username, :password, :first_name, :last_name");*/
        //$stmt->bindParam(':id', 1);

        $username = $this->username;
        $password = password_hash($this->password, PASSWORD_BCRYPT);
        $email = $this->email;
        $date_created = strftime("%Y-%m-%d %H:%M:%S", time());

        /*$username = "boiy";
        $password = password_hash("redrum", PASSWORD_BCRYPT);
        $email = "bdboiy@gmail.com";
        $date_created = strftime("%Y-%m-%d %H:%M:%S", time());*/

        $stmt->bindParam(':username', $username, PDO::PARAM_STR);
        $stmt->bindParam(':password', $password, PDO::PARAM_STR);
        $stmt->bindParam(':email', $email, PDO::PARAM_STR);
        $stmt->bindParam(':date_created', $date_created, PDO::PARAM_STR);

        if($stmt->execute()) {
            $this->id = $core->con->lastInsertId();
            echo "New records created successfully";
            return true;
        } else {
            return false;
        }

    } catch (PDOException $e) {
        echo "Insert Error: " . $e->getMessage();
    }
}

那就是创建一个新用户。它奏效了。

然后我尝试登录用户:

if($session->is_logged_in()) {redirect_to("admin.php");}

// Remember to give your form's submit tag a name="submit" attribute!
if (isset($_POST['submit'])) { // Form has been submitted.

    $username = trim($_POST['username']);
    $password = trim($_POST['password']);
    $YRJWA = "YRJWA";
    $string = "$2y$10$$YRJWA/EJQGkmqev6VlpteOXHwF6DeQWcU1x1uGqmOdY4CDK5.oJYi";

    // Check database to see if username/password exist.
    $found_user = User::authenticate($username, $string);


    if ($found_user) {
        //if (password_verify($password, $found_user->password)) {
            $session->login($found_user);
            log_action('Login', "{$found_user->username} logged in.");
            redirect_to("admin.php");
        //}
    } else {
        // username/password combo was not found in the database
        $message = "Username/password combination incorrect.";
    }

} else { // Form has not been submitted.
    $username = "";
    $password = "";
}

当我这样做时,它不起作用。 当我输入 password_verify 时,它不起作用,所以我将其注释掉,如上面的代码所示。

然后我创建了一个新页面并在那里测试了我的代码:

$YRJWA = "YRJWA";
$string = "$2y$10$$YRJWA/EJQGkmqev6VlpteOXHwF6DeQWcU1x1uGqmOdY4CDK5.oJYi";
//$string = 'redrum';
echo "<hr>";
$found_user = User::authenticate('boiy', $string);
print_r($found_user);
echo "<br>";
/*echo strlen($found_user->password);*/
/*echo utf8_encode($found_user->password);
echo utf8_decode($found_user->password);*/
echo "<br/>";
//echo substr($found_user->password, 0, 60);
var_dump($found_user->password);

echo "<br>";
if(password_verify('redrum', $found_user->password)) {
    echo "Valid";
} else {
    echo "Invalid";
}
ConnectionManager::close();

当我直接从数据库使用密码时,它返回正确的数据并打印“有效”。

当我删除评论并尝试“redum”时出现此错误

Notice: Trying to get property of non-object in C:\xampp\htdocs\WealthPlus\private\index.php on line 36 NULL

Notice: Trying to get property of non-object in C:\xampp\htdocs\WealthPlus\private\index.php on line 39 Invalid

public static function authenticate($username="", $password="") {
    $sql  = "SELECT username, password FROM users WHERE username = :username AND password = :password LIMIT 1";
    try {

            $core = ConnectionManager::getInstance();
            $stmt = $core->con->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
            $stmt->execute([':username' => $username, ':password' => $password]);
            $stmt->setFetchMode(PDO::FETCH_CLASS, "User");
            $users = $stmt->fetch();
        //if (password_verify($password, $users->password)) {
            return $users;
        //}
    //return !empty($users) ? array_shift($users) : false;
    }catch (PDOException $e) {
        echo "Error: " . $e->getMessage();
    }
}

最佳答案

如果您保存的是散列密码,则无法通过密码查找。您需要做的是获取用户记录,然后使用 password_verify 验证密码.

你甚至有这样的代码被禁用了:

public static function authenticate($username, $password) {
    try {
        $core = ConnectionManager::getInstance();
        $stmt = $core->con->prepare("SELECT password FROM users WHERE username = :username";, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
        $stmt->execute([ ':username' => $username ]);
        $stmt->setFetchMode(PDO::FETCH_CLASS, "User");

        $user = $stmt->fetch();

        if (password_verify($password, $user['password'])) {
            return $users;
        }
    } catch (PDOException $e) {
        echo "Error: " . $e->getMessage();

        return false;
    }
}

请记住,对username 之类的内容添加UNIQUE 约束,您无需担心LIMIT 1,因为这是不可能的得到两行。

关于php - Password_Hash、Mysql、SetFetchMode、Password_verify,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39736118/

相关文章:

php - mysql 选择价格范围 php

php - 如何在 yii 中运行累积派生查询

php - 使用 php 生成脚本或使用 json

php - 在 cUrl 中获取 400 错误请求 - PHP

php - 1250 - 来自其中一个 SELECT 的表 'sub' 不能在全局 ORDER 子句中使用

php - 无法使用 rpc xml 将内容写入文件

javascript - Flask 谷歌地图 API 中的多个标记

mysql - SQL语句重构

php - 如何统计最后: hour/day/week/month/year ?中访问次数最多的页面 - PHP+MySQL

php - 如何仅推出表中唯一行的 JSON?