使用 PDO 准备语句插入密码哈希

发布于 2024-08-04 03:07:03 字数 385 浏览 8 评论 0原文

在基本的 mysql 插入中,您可以设置密码变量“PASSWORD($password)”,但这会破坏 PDO 语句。

使用 pdo::prepare 和 pdo::execute 时如何散列密码?

$sql= "INSERT INTO contractors (userid, password, name) VALUES ('$userid', '$pass1', '$name')";
$result = $dbh->prepare($sql);
$count = $result->execute();

Echo $count."<br>";

我真是个n00b,一个简单的注册页面花了我两天时间。欢迎幼儿园的答案。

谢谢,

In a basic mysql insert you are able to set a password variable 'PASSWORD($password)' but this breaks a PDO statement.

How do you hash the password while using pdo::prepare and pdo::execute?

$sql= "INSERT INTO contractors (userid, password, name) VALUES ('$userid', '$pass1', '$name')";
$result = $dbh->prepare($sql);
$count = $result->execute();

Echo $count."<br>";

I am such a n00b, a simple registration page has taken me two days. Kindergarten answers are welcomed.

thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

寂寞笑我太脆弱 2024-08-11 03:07:03

注意

这个答案最初推荐使用无盐哈希。现在这很愚蠢,所以它被重写以将其带入现代。请注意旧内容中类似的现在很糟糕的答案。

您正在使用 PDO,因此您应该使用带有占位符的参数化查询:

$sql= "INSERT INTO contractors (userid, password, name) VALUES (?, ?, ?)";
$result = $dbh->prepare($sql);
$count = $result->execute(array($userid, $pass1, $name));

echo $count."<br>";

在现代,您应该使用 Blowfish/bcrypt 而不是 MD5 或 SHA1。从 PHP 5.3 开始,您可以将 crypt$2y$ 一起使用 前缀。从 PHP 5.5 开始,您可以使用 password_hash 代替。同时您可以使用ircmaxell 的password_compat 库

这是一个使用 crypt非常低难度值的演示。请注意,我们还存储了盐。虽然我在此演示中对盐进行了硬编码,但您应该为每个用户使用唯一的盐。

$salt = 'saltysaltsaltsalt'; 
$password_hash = crypt($pass1, '$2a$07

验证密码就像使用相同参数重建哈希一样简单。

$sth = $dbh->prepare('SELECT password, salt FROM contractors WHERE userid = ?');
$sth->execute(array($userid));
list($existing_hash, $salt) = $sth->fetch(PDO::FETCH_NUM);
unset($sth);

$new_hash = crypt($pass1, '$2a$07
 . $salt);
$sql= "INSERT INTO contractors (userid, password, salt, name) VALUES (?, ?, ?, ?)";
$result = $dbh->prepare($sql);
$count = $result->execute(array($userid, $password_hash, $salt, $name));

echo $count."<br>";

验证密码就像使用相同参数重建哈希一样简单。


 . $salt);
if($new_hash === $existing_hash) {
    echo "Password matched.";
} else {
    echo "Password did not match.";
}
. $salt); $sql= "INSERT INTO contractors (userid, password, salt, name) VALUES (?, ?, ?, ?)"; $result = $dbh->prepare($sql); $count = $result->execute(array($userid, $password_hash, $salt, $name)); echo $count."<br>";

验证密码就像使用相同参数重建哈希一样简单。

Note

This answer originally recommended an unsalted hash. That's silly nowadays, so it's been rewritten to bring it into the modern era. Watch out for similar now-bad answers in older content here on SO.

You're using PDO, so you should be using parameterized queries with placeholders:

$sql= "INSERT INTO contractors (userid, password, name) VALUES (?, ?, ?)";
$result = $dbh->prepare($sql);
$count = $result->execute(array($userid, $pass1, $name));

echo $count."<br>";

In the modern era, you should us Blowfish/bcrypt instead of MD5 or SHA1. As of PHP 5.3, you can use crypt with the $2y$ prefix. As of PHP 5.5, you'll be able to use password_hash instead. You can use ircmaxell's password_compat library in the mean time.

Here's a demo using crypt and a very low difficulty value. Note that we're also storing the salt. While I've hard-coded the salt here in this demo, you should use a unique salt per user.

$salt = 'saltysaltsaltsalt'; 
$password_hash = crypt($pass1, '$2a$07

Verifying the password is as easy as reconstructing the hash using the same parameters.

$sth = $dbh->prepare('SELECT password, salt FROM contractors WHERE userid = ?');
$sth->execute(array($userid));
list($existing_hash, $salt) = $sth->fetch(PDO::FETCH_NUM);
unset($sth);

$new_hash = crypt($pass1, '$2a$07
 . $salt);
$sql= "INSERT INTO contractors (userid, password, salt, name) VALUES (?, ?, ?, ?)";
$result = $dbh->prepare($sql);
$count = $result->execute(array($userid, $password_hash, $salt, $name));

echo $count."<br>";

Verifying the password is as easy as reconstructing the hash using the same parameters.


 . $salt);
if($new_hash === $existing_hash) {
    echo "Password matched.";
} else {
    echo "Password did not match.";
}
. $salt); $sql= "INSERT INTO contractors (userid, password, salt, name) VALUES (?, ?, ?, ?)"; $result = $dbh->prepare($sql); $count = $result->execute(array($userid, $password_hash, $salt, $name)); echo $count."<br>";

Verifying the password is as easy as reconstructing the hash using the same parameters.

怎会甘心 2024-08-11 03:07:03
<?php
try {
  $dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $stmt = new PDOStatement();

  $hash = sha1($pass . $dataUniqueToEachUser);
  $stmt = $dbh->prepare("INSERT INTO Users(name, email, hash) VALUES (:name, :email, :hash)");
  $stmt->bindParam(':name', $_POST['username'], PDO::PARAM_STR);
  $stmt->bindParam(':email', $_POST['email'], PDO::PARAM_STR);
  $stmt->bindParam(':hash', $hash, PDO::PARAM_STR);
  $stmt->execute();

  if ($stmt->rowCount() == 0) {
   $valid = true;
  }
}
catch (PDOException $e) {
  echo "An error occurred: {$e}";
}
?>
<?php
try {
  $dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $username, $password);
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $stmt = new PDOStatement();

  $hash = sha1($pass . $dataUniqueToEachUser);
  $stmt = $dbh->prepare("INSERT INTO Users(name, email, hash) VALUES (:name, :email, :hash)");
  $stmt->bindParam(':name', $_POST['username'], PDO::PARAM_STR);
  $stmt->bindParam(':email', $_POST['email'], PDO::PARAM_STR);
  $stmt->bindParam(':hash', $hash, PDO::PARAM_STR);
  $stmt->execute();

  if ($stmt->rowCount() == 0) {
   $valid = true;
  }
}
catch (PDOException $e) {
  echo "An error occurred: {$e}";
}
?>
别想她 2024-08-11 03:07:03

如果您想使用 MD5 进行散列,则可以在构造 SQL 语句之前对密码执行以下操作:

$pass1 = md5($pass1);
$sql = "INSERT INTO contractors ( userid, password, name ) VALUES ( '$userid', '$pass1', '$name' )";
$result = $dbh->prepare($sql);
$count = $result->execute();

echo $count."<br>";

即使它是另一个散列函数,其思想也是相同的。在构建 SQL 语句之前对密码进行哈希处理。

作为 FiarrVoteyDisciple 在下面的评论中指出,选择 SHA 哈希,因为它更安全。

sha1()

If you wanted to hash using MD5, you could do the following with the password before constructing the SQL statement:

$pass1 = md5($pass1);
$sql = "INSERT INTO contractors ( userid, password, name ) VALUES ( '$userid', '$pass1', '$name' )";
$result = $dbh->prepare($sql);
$count = $result->execute();

echo $count."<br>";

The idea is the same even if it is another hash function. Hash the password before constructing the SQL statement.

As Fiarr and VoteyDisciple have noted in the comments below, opt for a SHA hash as it is more secure.

sha1()

撩人痒 2024-08-11 03:07:03

如果您创建自己的哈希可能会更安全(并且可能更简单更困难)。在我看来,最好的解决方案是通过连接表中的多个字段来创建哈希,如下所示:

$pass1 = sha1($pass1.$name);

注意:如上所述,md5 不是最安全的解决方案,因为目前互联网上有很多数据库与 md5 哈希变量关联的关键字,使想要破解您系统的人变得更容易。

It's perhaps more safe if you create your own hash (and perhaps more simple tough). The best sollution, in my oppinion, is to create a hash by joining several fields from the table, like this:

$pass1 = sha1($pass1.$name);

Note: md5, as suggested above, isn't the saffest sollution, since currently there's a lot of databases over the internet with keywords associated to md5 hash variables, making it easier to someone who wants to hack your system.

我不会写诗 2024-08-11 03:07:03

使用这样的变量替换会使您的应用程序广泛容易受到 SQL 注入攻击,除非您要转义 $userid 以及您粘贴的代码之前的内容。

更好地使用 PDO 的替换功能(我的意思是,您已经在调用 .prepare):

$sql = "INSERT INTO contractors (userid, password, name) VALUES (?, PASSWORD(?), ?)";
$query = $dbh->prepare($sql);
$dbh->execute(array($userid, $pass1, $name));

我不确定像这样的内联 PASSWORD() 是否有效 - 如果我错了,请纠正我。如果你想采用 Alan 的方法而不依赖 MySQL 来散列你的密码(明智的),你也可以这样做:

$sql = "INSERT INTO contractors (userid, password, name) VALUES (?, ?, ?)";
$query = $dbh->prepare($sql);
$dbh->execute(array($userid, sha1($hashed), $name));

也可以考虑使用盐:

$hashed = sha1("SaltedPassword" . $pass1);

Using variable substitution like that makes your app wide open to SQL injection attacks, unless you are escaping $userid and the lot before the code you pasted.

Better to use PDO's substitution abilities (I mean, you're already calling .prepare):

$sql = "INSERT INTO contractors (userid, password, name) VALUES (?, PASSWORD(?), ?)";
$query = $dbh->prepare($sql);
$dbh->execute(array($userid, $pass1, $name));

I'm not sure if inlining PASSWORD() like that will work -- please correct me if I'm wrong. If you want to take Alan's approach and not rely on MySQL to hash your passwords (wise), you can also do something like this:

$sql = "INSERT INTO contractors (userid, password, name) VALUES (?, ?, ?)";
$query = $dbh->prepare($sql);
$dbh->execute(array($userid, sha1($hashed), $name));

Consider using a salt as well:

$hashed = sha1("SaltedPassword" . $pass1);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文