如何使用password_verify()从数据库中检索密码


How to retrieve password from database with password_verify()?

我正在学习PHP,作为一个项目,我开始建立一个社交网络。我确实创建了注册表单和登录表单,我可以将用户添加到我的数据库。我也对他们的密码进行哈希处理。这是一个简单的网站,工作正在进行中,所以有很多安全漏洞。

我的问题是登录文件,我似乎无法匹配用户和他给我的密码。为了验证用户密码,我使用password_verify()函数,但它似乎不能正常工作。

下面是我的代码:

<?php
//signUp.php
//Here is where I add a user in my database
//I validate the input, confirm that the password is written like it  should be
//check if a user with the same username exists in the database
//if all checks out I will add the user in the database
   //and redirect the user to his profile
   require_once 'login.php';
   require_once 'helperFunctions.php';
$conn = new mysqli($servername, $username, $password, $database);
if(!$conn)
   die("Connection failed:" . mysqli_connect_error());
$myUsername = $_POST['Name'];
$myPassword = $_POST['Password'];
$myConfirm = $_POST['conPass'];
sanitize($conn, $myUsername);
sanitize($conn, $myPassword);
//check if the two passwords are the same
if($myPassword != $myConfirm){
  print "Your passwords don't match";
  header("refresh: 5; index.html");
} else {
   //check if username already exists in database
    $query = "SELECT * FROM members WHERE Username='$myUsername'";
    $result = mysqli_query($conn, $query);
    $count  = mysqli_num_rows($result);
    if($count == 0){
        //hash password
        $hashedPass = password_hash("$myPassword", PASSWORD_DEFAULT);
        //username doesn't exist in database 
        //add user with the hashed password
        $query ="INSERT INTO members (Username, Password) VALUES     ('{$myUsername}', '{$hashedPass}')";
        $result = mysqli_query($conn, $query);
        if(!$result)
            die("Invalid query: " . mysqli_error());
        else{
            print "You are now a member or The Social Network";
            header("refresh: 5; login_success.php");
        }
    } else {
        print "Username already exists";
        header("refresh: 5; index.html");
    }
}
?>

登录

<?php
//checkLogin.php
//Here is where I authenticate my users and if successfull I will show  them their profile
require_once 'login.php';
require_once 'helperFunctions.php';
$conn = new mysqli($servername, $username, $password, $database);
if(!$conn)
    die("Connection failed:" . mysqli_connect_error());
//Values from form
$myUsername = $_POST['Name'];
$myPassword = $_POST['Password'];
//sanitize input
sanitize($conn, $myUsername);
sanitize($conn, $myPassword);
$query = "SELECT * FROM members WHERE Username='$myUsername'";
$result = mysqli_query($conn, $query);
$count = mysqli_num_rows($result);
if($count == 1){
    $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
    print "hashedPass = ${row['Password']}";
    print "myPassword: " . $myPassword;
    if(password_verify($myPassword, $row['Password'])){
        print "Password match";
    } else
        print "The username or password do not match";
} 
?>
<<p> 清洁功能/strong>
    function sanitize($conn, $val){
    $val = stripslashes($val);
    $val = mysqli_real_escape_string($conn, $val);
}

通过运行程序print "hashedPass = ${row['Password']}";打印出哈希密码,这与我在数据库上的密码相同,但由于某种原因,我在此之后被重定向到print "The username or password do not match";语句。

从已删除的回答中提取的评论:

"我记得当我第一次创建数据库时,我使用CHAR(10)作为密码,而散列密码需要更多字符。"

所以这里万能的答案是你的密码列是50个字符短。

password_hash()创建一个60个字符的字符串。

手册指出,为了适应将来的变化,最好使用长度为255的VARCHAR。

  • http://php.net/manual/en/function.password-hash.php

现在解决这个问题的办法是重新注册,然后用你现在使用的重新登录。

手册中的例子:

<?php
/**
 * We just want to hash our password using the current DEFAULT algorithm.
 * This is presently BCRYPT, and will produce a 60 character result.
 *
 * Beware that DEFAULT may change over time, so you would want to prepare
 * By allowing your storage to expand past 60 characters (255 would be good)
 */
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."'n";
?> 
上面的示例将输出类似于:

2 y 10美元美元.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

同样来自手册:

谨慎

对算法参数使用PASSWORD_BCRYPT将导致密码参数被截断为最大长度为72个字符。

PASSWORD_DEFAULT -使用bcrypt算法(PHP 5.5.0默认)。请注意,这个常量被设计为随着PHP中添加新的和更强的算法而随时间变化。因此,使用此标识符产生的结果的长度可能会随时间变化。因此,建议将结果存储在可以扩展超过60个字符的数据库列中(255个字符将是一个不错的选择)。

PASSWORD_BCRYPT -使用CRYPT_BLOWFISH算法创建哈希。这将使用"$2y$"标识符生成一个标准的crypt()兼容散列。结果将始终是一个60个字符的字符串,如果失败则返回FALSE。
支持选项:

从删除的答案中提取的另一个评论/问题:

"我可以修改我的密码字段而不必删除我的表并从头开始吗?"

答案是肯定的。参见这个关于Stack的问题&A:

    如何修改mysql表中列的大小?

你也可以参考:

  • https://dev.mysql.com/doc/refman/5.0/en/alter-table.html

旁注:您仍然需要为(旧的)受影响的列重新输入新的哈希值。

加,如前所述;你对SQL注入是开放的。使用预处理语句:

  • https://en.wikipedia.org/wiki/Prepared_statement