1

所以我有一个 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();
        }
    }
}
?>

那么它看起来如何?

4

2 回答 2

1

如果不进行测试,我认为您的代码应该可以工作,BCrypt 的使用看起来很合理。当然,有些地方可以改进,有些可能是见仁见智。

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

未经测试的例子:

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

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

希望我能给你一些想法。

于 2012-10-04T19:56:44.913 回答
0

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

 SELECT COUNT(*) FROM Conference
 WHERE Username = :un
 AND Password = ENCRYPT(:pass, Password)
 LIMIT 1
于 2012-10-04T19:04:50.797 回答