从 MySQL 数据库中提取哈希用户名
Pulling a hashed username from MySQL database
我正在从事一个项目,其中用户名和密码都需要使用 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
中生成和存储的散列与数据库中的散列不匹配。这可以解释为什么没有结果被提取。有办法解决这个问题吗?
这不加密,它散列:
$encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);
也就是说,这是一种方式。您(理论上)永远无法从中取回原始文本。每次 运行 它也会产生不同的结果。因此,您永远无法通过 运行 带有 WHERE
子句的查询来挑选出一个匹配的用户。相反,您必须遍历系统中的每个用户,运行ning password_verify()
针对每个用户。
所以...不要那样做。以纯文本形式保留用户名,以便您可以从数据库索引中受益。
你想做的事情无法完成,因为以明文形式存储用户名正是让你确定你需要验证的确切凭据(即 table 行)的原因。
想象一下,无论如何你都试过了。您想要验证 john.doe
。您必须循环每个存储的用户名哈希,获取相应的盐,以便您可以使用 john.doe
和当前行盐计算哈希,然后比较两个用户名哈希。如果没有匹配项,请转到下一行......直到您最终获得匹配项并最终确定要检查的密码哈希。所有这一切,所有算法都专门设计为慢。去图吧。
我正在从事一个项目,其中用户名和密码都需要使用 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
中生成和存储的散列与数据库中的散列不匹配。这可以解释为什么没有结果被提取。有办法解决这个问题吗?
这不加密,它散列:
$encrypteduser = password_hash($submittedUser, PASSWORD_ARGON2I);
也就是说,这是一种方式。您(理论上)永远无法从中取回原始文本。每次 运行 它也会产生不同的结果。因此,您永远无法通过 运行 带有 WHERE
子句的查询来挑选出一个匹配的用户。相反,您必须遍历系统中的每个用户,运行ning password_verify()
针对每个用户。
所以...不要那样做。以纯文本形式保留用户名,以便您可以从数据库索引中受益。
你想做的事情无法完成,因为以明文形式存储用户名正是让你确定你需要验证的确切凭据(即 table 行)的原因。
想象一下,无论如何你都试过了。您想要验证 john.doe
。您必须循环每个存储的用户名哈希,获取相应的盐,以便您可以使用 john.doe
和当前行盐计算哈希,然后比较两个用户名哈希。如果没有匹配项,请转到下一行......直到您最终获得匹配项并最终确定要检查的密码哈希。所有这一切,所有算法都专门设计为慢。去图吧。