【问题标题】:Password_verify in PHPPHP中的密码验证
【发布时间】:2015-07-27 23:08:01
【问题描述】:

所以我允许用户使用用户名和密码创建帐户。当用户使用以下方法创建新帐户时,我已设法加密密码:

$hash = password_hash($password, PASSWORD_BCRYPT);

但是我在登录时遇到了密码验证问题,有人可以帮我解决我的问题吗?我知道是这样的:

password_verify($password, $hash)

但我不知道如何构造它或在代码中的何处添加它。提前致谢。这就是我所拥有的:

<?php
if (isset($_GET["username"])  && isset($_GET["password"]) ){
    $username = $_GET["username"];
    $password = $_GET["password"];
    $result = login( $username, $password);
    echo $result;
}

function makeSqlConnection()
{
    $DB_HostName = "";
    $DB_Name = "";
    $DB_User = "";
    $DB_Pass = "";

    $con = mysql_connect($DB_HostName,$DB_User,$DB_Pass) or die(mysql_error()); 

    mysql_select_db($DB_Name,$con) or die(mysql_error()); 

    return $con;
}

function disconnectSqlConnection($con)
{
    mysql_close($con);
}

function login($username, $password)
{
    $con = makeSqlConnection();
    $sql = "select * from login  where username = '$username' and password = '$password';";
    $res = mysql_query($sql,$con) or die(mysql_error());

    $res1 = mysql_num_rows($res);

    disconnectSqlConnection($con);

     if ($res1 != 0) {
        return 1;
    }else{
        return 0;
    }// end else

}// end of Function 
?>

【问题讨论】:

  • 在登录功能中,选择时只选择用户名。从选择结果中获取密码并使用password_verify
  • 尝试使用PDOmysqli 作为数据库,因为不再支持`mysql`。
  • 老实说不知道你为什么使用 mysql_ 和 PHP 5.5 密码散列方法。
  • 如果你使用password_hashpassword_verify这意味着你的PHP版本> 5.5。为什么要使用 mysql 扩展?
  • 谢谢@frz3993 成功了!

标签: php mysql password-hash


【解决方案1】:

一般做法如下:

  1. 从数据库中获取password 哈希,其中username = 输入的用户名。
  2. 如果找到行,则说明存在用户
  3. 现在您将输入的密码与存储在数据库中的哈希值进行比较。

我将在这里用一些伪代码为您概述上述流程:

$query = SELECT password FROM users WHERE username = '$username'

$data = FETCH_THE_DATA($query);

if(password_verify($USER_INPUTTED_PASSWORD, $data['password'])) {
    // password is correct
} else {
    // password is in-correct
}

备注

  • 停止使用mysql_* 函数。该库已被弃用,因为它不可靠,并将在 PHP 的未来版本中删除。
  • 您应该始终阅读手册 - password_verify(),其中明确指出您将“用户输入的密码”与存储在数据库中的散列版本进行比较。

【讨论】:

    【解决方案2】:

    今天心情很好,困了,就写一堆代码吧。

    这是一个如何将 PDO 与准备好的语句一起使用的示例。您将不得不根据您的需要对其进行调整,并且您还必须检查帖子/获取是否不为空。 我更喜欢使用 POST 请求登录,所以这个例子将使用 POST 请求。

    这是我的用户类。它使用占位符和绑定,而不是直接将参数传递到查询中。这将为 SQL 注入攻击提供一些保护。

    class User{
    
        private $dbh;
    
    
        function __construct(){
    
            $this->dbh = new PDO("mysql:host=".DB_SERVER.";dbname=".DB_NAME.';charset=utf8mb4', DB_USER, DB_PASSWORD) or die('db connect error');
        }
    
    
        function create($username, $password){
    
            $status = false;
    
            try{
    
                $stmt = "INSERT INTO login (username, password)
                            VALUES (?, ?)";
    
                $qry = $this->dbh->prepare($stmt);
    
                $qry->bindParam(1, $username);
                $qry->bindParam(2, $password);
    
                $status = $qry->execute();
            }catch(PDOException $e){
    
                $e->getMessage();
            }
    
            $qry->closeCursor();
    
            return $status;        
    
        }
    
        public function getPassword($username){
    
            $status = false;
            try{
                $stmt = "SELECT * FROM login WHERE username = ? LIMIT 1";
    
                $qry = $this->dbh->prepare($stmt);
                $qry->bindParam(1, $username);
                $qry->execute();
    
                $status = $qry->fetch(PDO::FETCH_ASSOC);
            }catch(PDOException $e){
    
                $e->getMessage();
            }
            $qry->closeCursor();
    
            return $status;
        }    
    
    }
    

    这是创建用户的方法。请注意,我不检查用户名是否已经存在。您可以自己实现它,也可以在用户名列上使用唯一索引,前提是排序规则不区分大小写。 我还增加了默认值 10 的成本,并且我定义了要使用的 PASSWORD_DEFAULT,因为我希望 PHP 引擎始终使用最强的可用算法(目前是 bcrypt)。

    function hashPassword($password){
    
                $password = password_hash($password, PASSWORD_DEFAULT,array('cost' => 16));
                return $password;
    }
    
    $user = new User;
    $_POST['password'] = hashPassword($_POST['password']);
    
    
    if(!$user->create(trim($_POST['username']),$_POST['password'])){
    
        echo 'Failed creating user';
    }else{
        echo 'User created';
    }
    

    这是验证密码的方法。

    $user = new User;
    $getPassword = $user->getPassword(trim($_POST['username']));
    
    if(!$getPassword){
    
        echo 'Error fetching user';
    }else{
    
        if(!password_verify($_POST['password'], $getPassword['password'])){
    
            echo 'Login failed';
        }else{
    
            echo 'Login successful';        
        }
    }
    

    【讨论】:

    • 我不知道我的评论是否合适,但我还是想说。这可能无济于事,因为用户可能不知道如何使用 PDO,因此不会理解您的代码。 OP 可能只是复制和粘贴代码,但仍然不明白它是如何工作的。不过你怎么解释就好了。现在只希望OP会阅读它。
    • 我明白你想说什么@SkyRamon,我很少放这样的代码。对于这个问题,OP实际上自己找到了答案,我只是指出了方向。 OP 可能甚至都不知道 OOP,所以希望他/她能学会它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    • 2017-06-22
    • 2016-03-02
    • 2017-07-06
    • 1970-01-01
    相关资源
    最近更新 更多