【问题标题】:PDO Fetching Bcrypted password?PDO 获取 Bcrypted 密码?
【发布时间】:2013-05-23 08:47:43
【问题描述】:

自从我第一次开始学习有关散列和加盐密码的知识以来,我的代码就遇到了很多麻烦。首先,我学习如何使用 MD5 对密码进行“散列”(是的,不要再这样做了),然后使用散列和 SHA256,最后使用 bcrypt(或者至少我认为它是 bcrypt)。这是我现在的注册码:

注册.php

<html>
<head>
<title>PDO - hashing algorithm</title>
</head>
<body>
    <?php
        if(isset($_POST['submit'])) {
            define( "DB_DSN", "mysql:host=localhost;dbname=test" );
            define ( "DB_USER", "root" );
            define ( "DB_PASS", "" );

            try {
            $connect = new PDO (DB_DSN, DB_USER, DB_PASS);
            $query = "CREATE TABLE IF NOT EXISTS `users` (
                    `id` INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL,
                    `username` VARCHAR(100) NOT NULL,
                    `password` VARCHAR(500) NOT NULL
            )ENGINE=InnoDB DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_swedish_ci;";
            $stmt = $connect->prepare($query);
            $stmt->execute();

            } catch (PDOException $e) {
                echo $e->getMessage();
            }
            // Let's hash the password
            $salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
            $hashedpassword = crypt($_POST['password']. '$2a$12$' .$salt);
        try {
        $query = "INSERT INTO `users` (`username`, `password`) VALUES (:username, :password)";
        $stmt = $connect->prepare($query);
        $stmt->execute(array(
                            ':username' => $_POST['username'],
                            ':password' => $hashedpassword
                        ));
                if ($stmt->rowCount() == 1) {
                    echo "Well done, user has registered successfully";

                } else {
                    echo "An error occured.. Please try again";
                }
        } catch (PDOException $e) {
            echo $e->getMessage();  
        }
    }
    ?>
    <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
    <p>Username: <input type="text" name="username"/></p>
    <p>Password: <input type="password" name="password" /></p>
    <input type="submit" name="submit" />
    </form>
</body>
</html>

此代码确实有效并且会加密密码,所以这不是我的主要问题。我的主要问题是,当我想创建登录页面时,如何比较用户输入的密码和存储在数据库中的密码?

这是我的 login.php 自动取款机。告诉我,如果你看到了我没有看到的东西,但我无法让它工作,它不会从数据库中输出用户名和密码。

<?php
        try {
        define( "DB_DSN", "mysql:host=localhost;dbname=test" );
        define ( "DB_USER", "root" );
        define ( "DB_PASS", "" );

            $connect = new PDO (DB_DSN, DB_USER, DB_PASS);

        } catch (PDOException $e) {

            echo $e->getMessage();
        }

        if(isset($_POST['submit'])) {

        $query = "SELECT * FROM `users` WHERE (username) = :username";
        $stmt = $connect->prepare($query);
        $stmt->execute(array(
                        ':username' => $_POST['username']
                        ));
            if($stmt->rowCount() == 0) {
                echo "User doesn't exist";
            } 
                $row = $stmt->fetch();

                if (crypt($_POST['password'], $row['password']) == $row['password']) {
                    echo $row['username']. $row['password'];
                } else {
                    return false;
                }
        }
    ?>

【问题讨论】:

  • 使用提供的用户 ID/名称从数据库中获取 bcrypt 哈希。获取的值应该包含盐和轮数以及散列的结果。然后使用它与提供的用户输入一起生成一个新的 bcrypt 值并进行比较 - 当且仅当它们是相同的值时,身份验证才有效。我很确定这在示例中有所体现。或者,更好的是,使用整洁的库/包装器。 (与没有盐的破解密码散列方法不同,它需要首先获取盐,以便它可以用于计算挑战散列。)
  • 我在下面使用代码示例编辑了我的评论,希望对您也有帮助。

标签: php mysql pdo fetch salt


【解决方案1】:

请参阅此链接以获取有关如何操作的教程:Using bcrypt to store passwords

编辑:

我发现了一些我的工作代码,我将在此处发布希望能有所帮助。

首先,我使用了一个自定义函数:

function better_crypt($input, $rounds = 7){
    $salt = "";
    $salt_chars = array_merge(range('A','Z'), range('a','z'), range(0,9));
    for($i=0; $i < 22; $i++) {
        $salt .= $salt_chars[array_rand($salt_chars)];
    }

    return crypt($input, sprintf('$2a$%02d$', $rounds) . $salt);
}

然后在第一次创建帐户时,将 $password_hash 存储在数据库中:

$password_hash = better_crypt($_POST['password']);

然后在登录时,将提交的密码与数据库中的密码哈希进行比较:

// $password = submitted login form password
// $row['password'] = the password hash in the database
if(crypt($password, $row['password']) == $row['password']) {
//Success!

【讨论】:

  • 我更新了我的评论,希望能更清楚、更有意义。
  • 感谢您的代码“sn-p”。它对我帮助很大!还有一个问题,尽管它有效。当您创建了 better_crypt 函数时,输入变量的值是多少?
  • 如果您查看我发布的第二个代码 sn-p,您会看到我将 $_POST['password'] 传递给了 better_crypt 函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多