将旧的md5密码转换为password_hash

时间:2019-06-08 08:05:21

标签: php md5

在php网站上将旧的md5密码更新为password_hash时遇到麻烦 我已经能够将所有文件更新为password_hash,而当成员下次登录

时,只是停留在更新数据库中的旧密码上

此处为原始代码

    $password = passhash($_POST["password"]);

    if (!empty($_POST["username"]) && !empty($_POST["password"])) {
        $res = SQL_Query_exec("SELECT id, password, secret, status, enabled FROM users WHERE username = " . sqlesc($_POST["username"]) . "");
        $row = mysqli_fetch_assoc($res);

        if ( ! $row || $row["password"] != $password )
            $message = T_("LOGIN_INCORRECT");
        elseif ($row["status"] == "pending")
            $message = T_("ACCOUNT_PENDING");
        elseif ($row["enabled"] == "no")
            $message = T_("ACCOUNT_DISABLED");
    } else
        $message = T_("NO_EMPTY_FIELDS");

此处带有password_hash

    $password = $_POST["password"];

    if (!empty($_POST["username"]) && !empty($_POST["password"])) {
        $res = SQL_Query_exec("SELECT id, password, secret, status, enabled FROM users WHERE username = " . sqlesc($_POST["username"]) . "");
        $row = mysqli_fetch_assoc($res);

        if ( !$row || !password_verify($password,$row["password"]))
            $message = T_("LOGIN_INCORRECT");
        elseif ($row["status"] == "pending")
            $message = T_("ACCOUNT_PENDING");
        elseif ($row["enabled"] == "no")
            $message = T_("ACCOUNT_DISABLED");
    } else
        $message = T_("NO_EMPTY_FIELDS");

我认为应该是这样,但是似乎无法在验证行之前使它工作

   if (strlen($password) > 40)
   {
   // Password already converted, verify using password_verify
   } else {

// User still using the old MD5, update it!
    if ($password = passhash($_POST["password"]))
    {
    // update to password_hash
    SQL_Query_exec("UPDATE users SET password WHERE username = " . 
    sqlesc($_POST["username"]) . "");
    }
}

2 个答案:

答案 0 :(得分:4)

我建议您暂时将旧的password保留在数据库中,并在其旁边创建一个更命名正确的新passwordHash。这样一来,即使您犯了错误,也总是可以退回到旧的做事方式。

当用户登录时,您确实可以访问未加密的密码。此时,您可以创建new hash

$password = $_POST["password"];
$passwordHash = password_hash($password, PASSWORD_DEFAULT);

之后,您需要实际存储新的哈希值:

SQL_Query_exec("UPDATE users 
                SET passwordHash = " . sqlesc($passwordHash) . "
                WHERE username = " . sqlesc($_POST["username"]));

那么,使用新的哈希仅仅是检查新哈希是否存在的问题。如果不是,则创建它,否则使用它。

过一会儿,当您知道新哈希在可靠地工作时,可以为拥有新哈希的用户(在备份之后!)从数据库中删除旧的MD5哈希。

注意:您正在转义用户输入,而不是使用准备好的语句。那不是最好的选择。参见:How to Prevent SQL Injection Vulnerabilities in PHP Applications上显示:

  

请勿通过转义或删除特殊字符来清理用户输入。   攻击者可以使用编码来绕过这种保护。

或者在the PHP manual itself中查看:

  

使用带有绑定变量的准备好的语句。

答案 1 :(得分:-1)

在最后一个示例中,您似乎正在检查输入密码的长度,而不是哈希密码。您需要先从数据库获取密码

if (!empty($_POST["username"]) && !empty($_POST["password"]))
{
    $password = $_POST["password"];
    $res = SQL_Query_exec("SELECT id, password, secret, status, enabled FROM users WHERE username = " . sqlesc($_POST["username"]) . "");
    $row = mysqli_fetch_assoc($res);
    if(strlen($row["password"]) == 40) // New hash
    {
        if ( !$row || !password_verify($password,$row["password"]))
            $message = T_("LOGIN_INCORRECT");
        elseif ($row["status"] == "pending")
            $message = T_("ACCOUNT_PENDING");
        elseif ($row["enabled"] == "no")
            $message = T_("ACCOUNT_DISABLED");
    }
    else                                // Old hash
    {
        $doUpdate = 1;
        $oldhash = passhash($password);
        if ( ! $row || $row["password"] != $oldhash )
        {
            $doUpdate = 0;
            $message = T_("LOGIN_INCORRECT");
        }
        elseif ($row["status"] == "pending")
            $message = T_("ACCOUNT_PENDING");
        elseif ($row["enabled"] == "no")
            $message = T_("ACCOUNT_DISABLED");
        if($doUpdate == 1) // Assuming all went well
                SQL_Query_exec("UPDATE users SET password = '" . newpasshashfunction($password) . "' WHERE username = " . sqlesc($_POST["username"]) . "");
    }
}
else
    $message = T_("NO_EMPTY_FIELDS");

此代码可以清除很多