【问题标题】:How to retrieve password from database with password_verify()?如何使用 password_verify() 从数据库中检索密码?
【发布时间】:2015-12-01 18:57:08
【问题描述】:

我正在学习 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"; 语句。

【问题讨论】:

  • 你在sanitize()函数中对$myPassword做了什么?向我们展示该代码
  • 您对 SQL 注入敞开了大门。如果有人说他们的用户名是'; DROP TABLE members;,你的 SQL 语句现在计算为SELECT * FROM members WHERE Username=''; DROP TABLE members;'。你需要使用PDO 之类的东西。 (我知道你说有安全漏洞,但这是一个很大的,所以我忍不住提一下)
  • @RiggsFolly 我添加了清理功能的代码
  • @bytesized 正如我提到的,这是正在进行中的工作,我首先要确保基础工作正常,然后我将处理 SQL 注入等
  • “当我第一次创建数据库时,我使用 CHAR(10) 作为密码,而哈希密码需要更多字符。” - 你猜怎么着,你有 50 个字符短.我就知道。这就是为什么我删除了我的评论,询问你它有多长和类型。可能没看过,现在只有主知道了。

标签: php sql validation password-encryption


【解决方案1】:

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

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

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

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

手册规定最好使用 VARCHAR,长度为 255,以适应未来的变化。

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

手册中的示例:

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

也来自手册:

注意 将 PASSWORD_BCRYPT 用于 algo 参数,将导致密码参数被截断为最大长度 72 个字符。

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

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

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

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

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

您也可以咨询:

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

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

【讨论】:

  • 这是正确的答案。抱歉回复晚了,没时间解决问题
  • @captain 不用担心。我很高兴听到我能够提供帮助,干杯
猜你喜欢
  • 2019-03-14
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
相关资源
最近更新 更多