How do I use password hashing with PDO to make my

2018-12-31 12:27发布

问题:

My code is actually working but it\'s not at all secure, I don\'t want to use MD5 as it\'s not all that secure. I\'ve been looking up password hashing but I\'m not sure how I would incorporate it into my code.

Login:

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

Register:

$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>\";

Could anyone show me how to incorporate it into the code I have?

回答1:

Just use a library. Seriously. They exist for a reason.

  • PHP 5.5+: use password_hash()
  • PHP 5.3.7+: use password-compat (a compatibility pack for above)
  • All others: use phpass

Don\'t do it yourself. If you\'re creating your own salt, YOU\'RE DOING IT WRONG. You should be using a library that handles that for you.

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

And on login:

$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
}


回答2:

About making your code more secure:

  • You should ALWAYS validate user entries, even from a POST method which can be changed by using firebug before submitting the form. As you are inserting the user input in a query, it\'s much more important.

About your question in general

As I advised you in the comment, use PHPass or already made APIs which will do the job for you.

You\'ll hash the username, pass and salt at account creation time and insert the hash in the database.

At authentication time, you\'ll regenerate a hash with the given login + password input and the information you added to generate the salt.

If both generated hashes match, then the user is authenticated.

EDIT: Yes password_hash is good also.



回答3:

Basically, you have two options, varying in complexity:

  • Store a Hash of the registered user\'s password, using a hashing algorithm of your choice (more into this later).
  • create a random salt (a constant, secret string) to be used together with the user\'s password, to create the hash as stated above and then store that hash in the DB.

When you retrieve the user record, you compare the hash computed from the provided password, with the hash stored in the DB.

Example:

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

or with a pre-defined SALT:

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

Store this into the DB as you did before.

Authenticating in done similarly:

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

and then retrieve from the DB based on that hash comparison to the stored one.

Now, I\'d like to address your concerns about Hashing algorithms: You dont have to use md5, you can as well use more secure hashing algorithms, refer to a comment here: PHP\'s hash function One suggestion is to use sha512 algorithm.

Most importantly, you should understand that hash is a one way conversion - there is no practical way to reverse engineer the original password from the hash alone, only perhaps finding alternative strings, which produce the same hash string.

I hope you find using a strong Hash algorithm, along with a Salt to mitigate the damage of a stolen Hash DB, good enough for your needs.