如何在 PDO 中使用密码散列来使我的代码更安全? [关闭]

Posted

技术标签:

【中文标题】如何在 PDO 中使用密码散列来使我的代码更安全? [关闭]【英文标题】:How do I use password hashing with PDO to make my code more secure? [closed] 【发布时间】:2015-06-28 22:29:56 【问题描述】:

我的代码实际上可以运行,但它一点也不安全,我不想使用 MD5,因为它不是那么安全。我一直在查找密码哈希,但我不确定如何将其合并到我的代码中。

登录:

require_once __DIR__.'/config.php';
session_start();

$dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_USERNAME, DB_USERNAME, DB_PASSWORD);

$sql = "SELECT * FROM users WHERE username = :u AND password = :p";
$query = $dbh->prepare($sql); // prepare
$params = array(":u" => $_POST['username'], ":p" => $_POST['password']);
$query->execute($params); // execute

$results = $query->fetchAll(); // then fetch


//hash passwords pls

if (count($results) > 0 )
$firstrow = $results[0];
$_SESSION['username'] = $firstrow['username'];
echo "Hello $username you have successfully logged in";
//header ("location:.php");

else
echo "Login Has Failed";
return;
 

注册:

$dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_USERNAME, DB_USERNAME, DB_PASSWORD);

$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];

$stmt = $dbh->prepare("insert into users set username='".$username."', email='".$email."', password='".$password."' ");
$stmt->execute();
echo "<p>Thank you, you are registered</p>";

谁能告诉我如何将它合并到我拥有的代码中?

【问题讨论】:

PHPass 是否满足您的需求?关于合并,您在身份验证时检查两个哈希,并在创建帐户时应用您想要的哈希。 旁注:您的注册部分不安全。现在,我敢打赌,我可以在 5 分钟内为您找到 50 个与此相关的链接。但那是你的工作。向我们展示您的尝试。 查看password_hash()。它内置于较新版本的 PHP 中。 @ircmaxell 我们不要忘记你的password_hash() compatibility pack 以防万一;-) 【参考方案1】:

只需使用库。严重地。它们的存在是有原因的。

PHP 5.5+:使用password_hash() PHP 5.3.7+:使用password-compat(以上兼容包) 所有其他人:使用phpass

不要自己做。如果您正在创建自己的盐,您做错了。您应该使用一个为您处理的库。

$dbh = new PDO(...);

$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
$hash = password_hash($password, PASSWORD_DEFAULT);

$stmt = $dbh->prepare("insert into users set username=?, email=?, password=?");
$stmt->execute([$username, $email, $hash]);

在登录时:

$sql = "SELECT * FROM users WHERE username = ?";
$stmt = $dbh->prepare($sql);
$result = $stmt->execute([$_POST['username']]);
$users = $result->fetchAll();
if (isset($users[0]) 
    if (password_verify($_POST['password'], $users[0]->password) 
        // valid login
     else 
        // invalid password
    
 else 
    // invalid username

【讨论】:

我有一种感觉,你正在把一些(有价值的)东西放在一起。 +100 为They exist for a reason. 您正在将用户的输入与存储的值进行比较以验证登录?那是行不通的。存储的值是散列的还记得吗?【参考方案2】:

关于让您的代码更安全

您应该始终验证用户条目,即使是通过 POST 方法,该方法可以在提交表单之前使用 firebug 进行更改。由于您在 查询插入 用户输入,因此它更为重要。

关于您的一般问题

正如我在评论中建议你的那样,使用 PHPass 或已经为你完成这项工作的 API。

您将在创建帐户时对用户名、pass 和 salt 进行哈希处理,并将哈希插入数据库中。

在身份验证时,您将使用给定的登录名 + 密码输入以及为生成 salt 而添加的信息重新生成哈希。

如果两个生成的哈希都匹配,则用户已通过身份验证。

编辑:是的,password_hash 也不错。

【讨论】:

如果你在创造自己的盐,那你就做错了。【参考方案3】:

基本上,您有两种选择,其复杂程度各不相同:

使用您选择的哈希算法存储注册用户密码的哈希值(稍后会详细介绍)。 创建一个随机盐(一个常量、秘密字符串)与用户密码一起使用,以创建如上所述的散列,然后将该散列存储在数据库中。

当您检索用户记录时,您会将根据提供的密码计算出的哈希值与存储在数据库中的哈希值进行比较。

例子:

$HashedPass = hash('sha512', $password);

或使用预定义的 SALT:

$HashedPass = hash('sha512', $password.SALT_STRING);

像以前一样将它存储到数据库中。

以类似方式进行身份验证:

$HashedPass = hash('sha512', $password.SALT_STRING);

然后根据与存储的哈希比较从数据库中检索。

现在,我想解决您对哈希算法的担忧: 您不必使用 md5,您也可以使用更安全的哈希算法,请参阅此处的评论: PHP's hash function 一种建议是使用 sha512 算法。

最重要的是,您应该了解哈希是一种单向转换 - 没有实用的方法可以单独从哈希中对原始密码进行逆向工程,只能找到替代字符串,它们会产生相同的哈希字符串。

我希望您发现使用强大的 Hash 算法以及 Salt 来减轻被盗 Hash DB 的损害,足以满足您的需求。

【讨论】:

以上是关于如何在 PDO 中使用密码散列来使我的代码更安全? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

散列哈希是不是使其更安全? [复制]

如何使用 PDO 以安全的方式显示和隐藏密码

在客户端散列密码是不是具有安全意义

存储密码的答案是否比存储密码更安全?

散列密码和加密密码之间的区别

使用 SHA-512 和 salt 来散列 MD5 散列密码?