我正在一个项目中,用户名和密码都需要使用Argon2进行哈希处理。在注册中将它们散列并将其插入数据库时,我没有任何麻烦,但是我无法提取登录信息。这是我的登录脚本:
<?php session_start(); ?>
<?php
include 'config.php';
if(isset($_POST['submit'])){
$submittedUser = $_POST['username'];
$submittedPass = $_POST['password'];
$encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);
$con=mysqli_connect($servername, $dbusername, $dbpassword, $dbname);
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
if ($stmt = mysqli_prepare($con, "SELECT * FROM users Where username =?")) {
mysqli_stmt_bind_param($stmt, "s", $encrypteduser);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
}
while($row = mysqli_fetch_array($result))
{
$username = $row['username'];
$password = $row['password'];
}
if (password_verify($submittedUser, $username) && password_verify($submittedPass, $password))
{
$_SESSION['user']=$username;
echo "<script> location.href='index.php'; </script>";
exit;
}
else
{
echo "<script> location.href='login.php'; </script>";
exit;
}
mysqli_close($con);
}
?>
我目前的理论是$encrypteduser
中生成和存储的哈希值与数据库中的哈希值不匹配。那可以解释为什么没有结果被撤消。有办法解决这个问题吗?
答案 0 :(得分:2)
这不会加密,会散列:
$encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);
也就是说,这是一种方式。您(理论上)永远无法从中获取原始文本。每次您运行它时,它也会产生不同的结果。结果,您将永远无法使用WHERE
子句运行查询来挑选一个匹配的用户。相反,您必须遍历系统中的每个用户,对每个用户运行password_verify()
。
所以...不要那样做。将用户名保留为纯文本格式,以便您可以从数据库索引中受益。
答案 1 :(得分:0)
您想要做的事情无法完成,因为将用户名保存为明文正是您可以确定要验证的确切凭据(即表格行)的原因。
想象一下您仍然尝试过。您要验证john.doe
。您必须循环访问每个存储的用户名哈希,获取相应的盐,以便可以使用john.doe
和当前行盐计算哈希,然后比较两个用户名哈希。如果没有匹配项,请转到下一行...,直到最终获得匹配项并最终确定要检查的密码哈希。所有这些,以及专门设计为 slow 的算法。走吧。