如何使用 PDO 的密码散列来使我的代码更安全?
How do I use password hashing with PDO to make my code more secure?
我的代码确实有效,但它一点也不安全,我不想使用 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>";
谁能告诉我如何将它合并到我的代码中?
关于让您的代码更安全:
- 您应该始终验证用户条目,即使是使用 POST 方法,也可以在提交表单之前使用 firebug 更改。当您在 查询 中 插入 用户输入 时,它就更重要了。
关于你的问题
正如我在评论中建议的那样,使用 PHPass 或已经为您完成工作的 API。
您将在创建帐户时对用户名、密码和加盐进行哈希处理,并将哈希值插入数据库。
在身份验证时,您将使用给定的登录名 + 密码输入以及您为生成盐而添加的信息重新生成哈希。
如果生成的两个哈希匹配,则用户通过身份验证。
编辑:是的 password_hash 也很好。
基本上,您有两种选择,复杂程度各不相同:
- 使用您选择的散列算法(稍后详细介绍)存储注册用户密码的散列。
- 创建一个随机盐(一个常量,秘密字符串)与用户密码一起使用,以创建如上所述的散列,然后将该散列存储在数据库中。
当您检索用户记录时,您将根据提供的密码计算出的哈希值与存储在数据库中的哈希值进行比较。
示例:
$HashedPass = hash('sha512', $password);
或使用预定义的 SALT:
$HashedPass = hash('sha512', $password.SALT_STRING);
像以前一样将其存储到数据库中。
以类似方式进行身份验证:
$HashedPass = hash('sha512', $password.SALT_STRING);
然后根据与存储的哈希比较从数据库中检索。
现在,我想解决您对哈希算法的担忧:
你不必使用 md5,你也可以使用更安全的哈希算法,参考这里的评论:
PHP's hash function
一个建议是使用sha512算法。
最重要的是,您应该了解散列是一种单向转换 - 没有实用的方法可以单独从散列中对原始密码进行逆向工程,只能找到替代字符串, 产生相同的散列字符串。
我希望您发现使用强大的哈希算法以及盐来减轻被盗哈希数据库的损害,足以满足您的需求。
就用图书馆吧。严重地。它们的存在是有原因的。
- 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
}
我的代码确实有效,但它一点也不安全,我不想使用 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>";
谁能告诉我如何将它合并到我的代码中?
关于让您的代码更安全:
- 您应该始终验证用户条目,即使是使用 POST 方法,也可以在提交表单之前使用 firebug 更改。当您在 查询 中 插入 用户输入 时,它就更重要了。
关于你的问题
正如我在评论中建议的那样,使用 PHPass 或已经为您完成工作的 API。
您将在创建帐户时对用户名、密码和加盐进行哈希处理,并将哈希值插入数据库。
在身份验证时,您将使用给定的登录名 + 密码输入以及您为生成盐而添加的信息重新生成哈希。
如果生成的两个哈希匹配,则用户通过身份验证。
编辑:是的 password_hash 也很好。
基本上,您有两种选择,复杂程度各不相同:
- 使用您选择的散列算法(稍后详细介绍)存储注册用户密码的散列。
- 创建一个随机盐(一个常量,秘密字符串)与用户密码一起使用,以创建如上所述的散列,然后将该散列存储在数据库中。
当您检索用户记录时,您将根据提供的密码计算出的哈希值与存储在数据库中的哈希值进行比较。
示例:
$HashedPass = hash('sha512', $password);
或使用预定义的 SALT:
$HashedPass = hash('sha512', $password.SALT_STRING);
像以前一样将其存储到数据库中。
以类似方式进行身份验证:
$HashedPass = hash('sha512', $password.SALT_STRING);
然后根据与存储的哈希比较从数据库中检索。
现在,我想解决您对哈希算法的担忧: 你不必使用 md5,你也可以使用更安全的哈希算法,参考这里的评论: PHP's hash function 一个建议是使用sha512算法。
最重要的是,您应该了解散列是一种单向转换 - 没有实用的方法可以单独从散列中对原始密码进行逆向工程,只能找到替代字符串, 产生相同的散列字符串。
我希望您发现使用强大的哈希算法以及盐来减轻被盗哈希数据库的损害,足以满足您的需求。
就用图书馆吧。严重地。它们的存在是有原因的。
- 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
}