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

标签 php sql validation password-encryption

我正在学习 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";
} 
?>

清理函数

    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"; 语句。

最佳答案

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

"I remembered that when I first created the database I used CHAR(10) for the passwords while the hashed password needs more characters."

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

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

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

现在解决这个问题的方法是重新注册,然后使用您当前使用的内容重新登录。

手册中的示例:

<?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";
?> 

上面的例子会输出类似于:

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

同样来自手册:

Caution Using the PASSWORD_BCRYPT for the algo parameter, will result in the password parameter being truncated to a maximum length of 72 characters.

PASSWORD_DEFAULT - Use the bcrypt algorithm (default as of PHP 5.5.0). Note that this constant is designed to change over time as new and stronger algorithms are added to PHP. For that reason, the length of the result from using this identifier can change over time. Therefore, it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice).

PASSWORD_BCRYPT - Use the CRYPT_BLOWFISH algorithm to create the hash. This will produce a standard crypt() compatible hash using the "$2y$" identifier. The result will always be a 60 character string, or FALSE on failure.
Supported Options:

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

"Can I alter my password field without having to delete my table and start from the beginning?"

答案是肯定的。在 Stack 上查看此问答:

您还可以咨询:

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

另外,如前所述;您对 SQL 注入(inject)持开放态度。使用准备好的语句:

关于php - 如何使用 password_verify() 从数据库中检索密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32418004/

相关文章:

php - 在 JS 不好的做法中使用 PHP if/else 吗?

sql查询中的python列表作为参数

javascript - 表单验证,所需输入,JS,尝试将这两个功能结合起来

validation - 在express-validator中出现错误后停止执行流程

sql - 如何有效地将新数据附加到 AWS Athena 中的表中?

Angular,如何为两个字段中的任何一个设置验证应在 react 形式方法中进行验证

php - Sonata 电子商务产品列表错误

php - 如何使用 ffmpeg 转换高质量的 .wmv 文件

php - 将多维数组访问到单个数组

mysql - 使用开始日期和结束日期列过滤所有数据