如何从数据库和身份验证用户中撤回加盐密码?

Posted

技术标签:

【中文标题】如何从数据库和身份验证用户中撤回加盐密码?【英文标题】:How to retract a salted password from the Database and auth user? 【发布时间】:2016-11-13 00:07:22 【问题描述】:

这是我第一次尝试使用所有存储在数据库 (mysql) 中的加盐密码来实现会员网站。除了“会员登录”页面中的错误之外,一切正常。

错误: 会员登录页面接受会员网站的任何条目,并且由于某种原因通过了我对$result === false的检查

这是检查成员是否存在的代码,请告诉我问题所在:

$servername = 'localhost';
$username = 'root';
$pwd = '';
$dbname = 'lp001';

$connect = new mysqli($servername,$username,$pwd,$dbname);

if ($connect->connect_error)
    die('connection failed, reason: '.$connect->connect_error);



$name = mysqli_real_escape_string($connect, $_POST['name']);
$password = mysqli_real_escape_string($connect, $_POST['password']);
$saltQuery = "SELECT salt FROM users WHERE name = '$name';";
$result = mysqli_query($connect, $saltQuery);
if ($result === false)
    die(mysqli_error());

$row = mysqli_fetch_assoc($result);
$salt = $row['salt'];

$saltedPW = $password.$salt;
$hashedPW = hash('sha256', $saltedPW);
$sqlQuery = "SELECT * FROM users WHERE name = '$name' AND password = '$hashedPW'";

if (mysqli_query($connect, $sqlQuery))
    echo '<h1>Welcome to the member site '.$name.'</h1>';
else
    echo 'error adding the query: '.$sql_q.'<br> Reason: '.mysqli_error($connect);

【问题讨论】:

看到这对你来说几乎是统包,登录部分,password_verify()在这里:***.com/a/33665819。它包括会话、错误报告和 try/catch SHA-* 算法不能安全地存储密码,而是使用函数password_hash() 来生成安全的 BCrypt 哈希。单独存放盐会变得不必要,看看这个answer。 @martinstoeckli - 谢谢你,如果你能把它写成代码,我会把它作为答案,在未来帮助我和其他人,再次感谢。 【参考方案1】:

开发人员经常在验证登录密码时遇到困难,因为他们不确定如何处理存储的密码哈希。他们知道密码应该使用像password_hash()这样的适当函数进行哈希处理,并将它们存储在varchar(255)字段中:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);

在登录表单中,我们无法直接用 SQL 验证密码,也无法搜索,因为存储的哈希是加盐的。相反,我们...

    必须从数据库中读取密码哈希,按用户 ID 搜索 然后可以使用password_verify() 函数根据找到的哈希检查登录密码。

您可以在下面找到一些示例代码,展示如何使用 mysqli 连接进行密码验证。该代码没有错误检查以使其可读:

/**
 * mysqli example for a login with a stored password-hash
 */
$mysqli = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
$mysqli->set_charset('utf8');

// Find the stored password hash in the db, searching by username
$sql = 'SELECT password FROM users WHERE username = ?';
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $_POST['username']); // it is safe to pass the user input unescaped
$stmt->execute();

// If this user exists, fetch the password-hash and check it
$isPasswordCorrect = false;
$stmt->bind_result($hashFromDb);
if ($stmt->fetch() === true)

  // Check whether the entered password matches the stored hash.
  // The salt and the cost factor will be extracted from $hashFromDb.
  $isPasswordCorrect = password_verify($_POST['password'], $hashFromDb);

请注意,该示例使用准备好的语句来避免 SQL 注入,在这种情况下不需要转义。从 pdo 连接读取的等效示例如下所示:

/**
 * pdo example for a login with a stored password-hash
 */
$dsn = "mysql:host=$dbHost;dbname=$dbName;charset=utf8";
$pdo = new PDO($dsn, $dbUser, $dbPassword);

// Find the stored password hash in the db, searching by username
$sql = 'SELECT password FROM users WHERE username = ?';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(1, $_POST['username'], PDO::PARAM_STR); // it is safe to pass the user input unescaped
$stmt->execute();

// If this user exists, fetch the password hash and check it
$isPasswordCorrect = false;
if (($row = $stmt->fetch(PDO::FETCH_ASSOC)) !== false)

  $hashFromDb = $row['password'];

  // Check whether the entered password matches the stored hash.
  // The salt and the cost factor will be extracted from $hashFromDb.
  $isPasswordCorrect = password_verify($_POST['password'], $hashFromDb);

【讨论】:

以上是关于如何从数据库和身份验证用户中撤回加盐密码?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将容器管理的身份验证与密码加盐一起使用?

php登录加密加盐

无密码身份验证如何保障用户隐私安全?

如何从 HTTP 基本身份验证中获取密码

如何将我的数据从 Firestore 转换为身份验证用户

如何执行我自己的身份验证(检查用户输入的用户名和密码)