Insert password hash using PDO Prepared Statements

无人久伴 提交于 2020-01-23 09:45:12

问题


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,


回答1:


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()




回答2:


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$' . $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.

$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);
if($new_hash === $existing_hash) {
    echo "Password matched.";
} else {
    echo "Password did not match.";
}



回答3:


<?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}";
}
?>



回答4:


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);



回答5:


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.



来源:https://stackoverflow.com/questions/1382215/insert-password-hash-using-pdo-prepared-statements

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!