在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"]) . "");
}
}
答案 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");
此代码可以清除很多