使用BCrypt进行PHP登录身份验证

时间:2012-10-04 18:44:35

标签: php mysql sql pdo bcrypt

所以我有一个php身份验证脚本,一切正常。但是我对我编程的方式非常不确定(我硬编了一些东西)而且我希望堆栈能看出来并指出任何潜在的问题。

这是脚本:

<?php
require_once 'Bcrypt.php';
class Mysql {
    private $conn;

    function __construct() {
        $this->conn =  new PDO('mysql:host=***;dbname=***;charset=UTF-8','***','***') or 
                      die('There was a problem connecting to the database.');
    }

    function verify_Username_and_Pass($un, $pwd) {
        ini_set('display_errors', 'On');
        error_reporting(E_ALL | E_STRICT);
        $query = "SELECT *
                FROM Conference
                WHERE Username = :un";

        $stmt = $this->conn->prepare($query);

        $stmt->bindParam(':un', $un);
        //$stmt->bindParam(':pwd', $pwd);
        $stmt->execute();
        $row = $stmt->fetchAll();
        $hash = $row[0]["Password"];
        $is_correct = Bcrypt::check($pwd, $hash);

        if ($is_correct) {
            // User exist
            $firstName = $row[0]["First Name"];
            $_SESSION["FirstName"] = $firstName;
            return true;
            $stmt->close();
        }
        else {
            // User doesn't exist
            return false;
            $stmt->close();
        }
    }
}
?>

那看起来怎么样?

2 个答案:

答案 0 :(得分:1)

如果不进行测试,我认为您的代码应该可行,BCrypt的使用看起来很合理。当然有一些要点可以改进,有些可能是意见问题。

  1. 如果您的查询未返回任何行(因为不存在此类用户名),您将访问无效索引$row[0]["Password"]。在使用之前,您应首先询问是否有结果。
  2. 您关闭数据库的请求放在return语句之后,因此永远不会执行。 PHP将自动关闭数据库,因此要么在return语句之前关闭它,要么删除该行。
  3. 您将函数命名为verify_username_and_password(),但实际上它也会从数据库中读取并写入会话。这些是隐藏的活动,另一个开发人员无法知道会话发生变化,除非他读取整个代码。解决这个问题的一种可能性是,将功能分开。
  4. 未经测试的例子:

    $userRow = getUserRowFromDatabase($userName);
    if (!is_null($userRow))
    {
      if (verifyPassword($password, $userRow["Password"]))
      {
        addLoggedInUserToSession($userRow["First Name"])
      }
    }
    

    这三个功能中的每一个都只有一个问题需要解决。这将使您的代码更具可读性,理想情况下应该像阅读书中的故事一样。

    希望我能给你一些想法。

答案 1 :(得分:0)

您实际上可以使用mysql为您验证哈希

 SELECT COUNT(*) FROM Conference
 WHERE Username = :un
 AND Password = ENCRYPT(:pass, Password)
 LIMIT 1