Reputation: 168
I have added the password_hash
PHP function to my registration page, where users create accounts and store passwords. I applied the same password_hash
line of code in the registration form. The data is saved in the database, but when I try to log in, the password submitted isn't matching the password stored. I also tried the password_verify
function, which I read in the PHP manual, but nothing works. I really don't know what else to do, after trying and trying, so if anybody has an advice, I'd appreciated it.
P.S. I'm currently using PHP version 5.6.25.
Here's the code:
<?php
// AJAX CALLS THIS LOGIN CODE TO EXECUTE
if(isset($_POST["e"])){
// CONNECT TO THE DATABASE
include_once("PHP_Includes/db.php");
// GATHER THE POSTED DATA INTO LOCAL VARIABLES AND SANITIZE
$e = mysqli_real_escape_string($db, $_POST['e']);
$p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
// FORM DATA ERROR HANDLING
if($e == "" || $p == ""){
echo "login_failed";
exit();
} else {
// END FORM DATA ERROR HANDLING
$sql = "SELECT id, username, password FROM users WHERE email='$e' AND activated='1' LIMIT 1";
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_row($query);
$db_id = $row[0];
$db_username = $row[1];
$db_pass_str = $row[2];
if($p != $db_pass_str){
echo "login_failed";
exit();
} else {
// CREATE THEIR SESSIONS
$_SESSION['userid'] = $db_id;
$_SESSION['username'] = $db_username;
$_SESSION['password'] = $db_pass_str;
}
}
exit();
}
?>
login() function:
function login(){
var e = _("email").value;
var p = _("password").value;
if(e == "" || p == ""){
_("status").innerHTML = "Fill out all of the form data";
} else {
_("loginbtn").style.display = "none";
_("status").innerHTML = 'please wait ...';
var ajax = ajaxObj("POST", "index.php");
ajax.onreadystatechange = function() {
if(ajaxReturn(ajax) == true) {
if(ajax.responseText == "login_failed"){
_("status").innerHTML = "Login unsuccessful, please try again.";
_("loginbtn").style.display = "block";
} else {
window.location = "user.php?u="+ajax.responseText;
}
}
}
ajax.send("e="+e+"&p="+p);
}
}
Upvotes: 1
Views: 258
Reputation: 26490
Your understanding of how password_hash()
works is a bit off. Unlike using sha1()
or md5()
(both of which you should avoid for storing passwords!), the password_hash()
doesn't return the same string for every time it's called, even for the same string.
For example:
var_dump(password_hash("hello_world", PASSWORD_DEFAULT));
var_dump(password_hash("hello_world", PASSWORD_DEFAULT));
would output (for example, the strings returned by password_hash()
varies for each time its called)
string(60) "$2y$10$Da2HG0dcvfI.3qBivR8Mpu9U5S06PBZ3415lDEh3EcDZ/fELZzHgC"
string(60) "$2y$10$zL6745UkPEvZWS5w1Keco.IKi7ssl.PqldGxucDYHaJW3vgCc366a"
Notice that they are different, even when the function is called twice on the same value? This means, that you cannot compare the stored password against $p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
like you are currently doing, because the password_hash()
function returns a different string every time - you need to use the function password_verify()
to verify the password, like below
$p = $_POST['p'];
if (password_verify($p, $fromDataBase)) {
// Valid password!
}
So instead of...
$p = password_hash($_POST['p'], PASSWORD_DEFAULT,['cost' => 15]);
you want
$p = $_POST['p'];
and instead of...
if($p != $db_pass_str){
you want
if (!password_verify($p, $db_pass_str)) {
And two notes on security:
You are not using prepared statements, which you REALLY should! See a link for mysqli_prepare()
below. You should treat all your user-input as dangerous, and therefor use prepared statements for all SQL queries that accepts user-input. (When using prepared statements, you don't want to use mysqli_real_escape_string()
- use one or the other, most preferably prepared statements!)
You are storing a password in a session - this is highly discouraged, as sessions can be "hijacked".
Readingmaterial:
Upvotes: 4