Jump to content
Larry Ullman's Book Forums

Chapter 13 - Securing Passwords with PHP


Recommended Posts

Greetings!

I'm so stuck and perhaps you can help me..

(BTW, I'm using the most current versions of PHP 7.2.1) and MYSQL... 

Everything has been working great going through the lessons, however, once I get to the "Securing Passwords with PHP" portion I'm not getting the results that are expected in the chapter.. 

1) I've updated "site name" database as per the requirements (ALTER TABLE users MODIFY COLUMN) and wiping out passwords (UPDATE users SET pass = ' ';)

2) I've updated the "register.php" old 9.5 script to reflect the new 13.7 script; even going as far as copying/pasting and validating it was a match.. ensuring that the new changes/lines were there.. 

3) When I register a new user, it works; it's even showing in my database... 

4) I've updated 'login_functions.inc.php to 13.8 script. 

Now here is the issue:

 - I can't log in as it's showing:

Error!

The following error(s) occurred:
- The email address and password entered do not match those on file.

Please try again.

 

I can't figure out why this is happening; I see my new registration in the DB but I can't log in. I'm not sure what other information I need to provide, but that's what I have right now.. Please help :)
- I've walked away from it several times, even going all the way back to Chapter 12 and starting over to see if I've missed anything.. 

Thanks in advance.. I LOVE your book! this is the second edition I've bought! I love the latest!

Jim Hipolito

Link to comment
Share on other sites

Hi Jim,

I'm not sure what technique you are using but since PHP 5.5+ there are PHP functions 'password_hash' to create a very strongly hashed password and 'password_verify' to check them.  You can see these if you Google for them.

I discussed this briefly with Larry a little while ago and he suggested using these.

Hope it helps.

Cheers

Link to comment
Share on other sites

Hey Jim,
Thanks for the nice words! I really appreciate it. There was an error in the SQL file (from my GitHub downloads) that set the length as too short. Did you use that? Or, put another way, what's the length of the password column you're using?

Link to comment
Share on other sites

  • 2 weeks later...

Hey nomadsoulkarma, yes it should be longer as stated in the book: you should use a varchar(256).

But the problem is the query :

$q = "SELECT user_id, first_name FROM users WHERE email='$e'";

And then you use :

if (password_verify($p, $row['pass']))

So it doesn't know the 'pass', that is why the login always fails.

You have to add to the query :

$q = "SELECT user_id, first_name, pass FROM users WHERE email='$e'";

Link to comment
Share on other sites

Thank You Montoya49 and Larry.  I changed the Select statement as adivsed but I'm not sure where to put :

if (password_verify($p, $row['pass'])) Seems like it should go on line 46 in  login_functions.inc.php. So I put it in place of: if (empty($pass))    But when I login I get the undefined variable error message.  I does not say what variable is undefined.  Must be $p

So here's the script after I made the changes, can you tell me if it is correct? Thanks.

 

 

Edited by nomadsoulkarma
no reason
Link to comment
Share on other sites

<?php # Script 12.2 - login_functions.inc.php
// This page defines two functions used by the login/logout process.

/* This function determines an absolute URL and redirects the user there.
 * The function takes one argument: the page to be redirected to.
 * The argument defaults to index.php.
 */
function redirect_user($page = 'index.php') {

    // Start defining the URL...
    // URL is http:// plus the host name plus the current directory:
    $url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']);

    // Remove any trailing slashes:
    $url = rtrim($url, '/\\');

    // Add the page:
    $url .= '/' . $page;

    // Redirect the user:
    header("Location: $url");
    exit(); // Quit the script.

} // End of redirect_user() function.


/* This function validates the form data (the email address and password).
 * If both are present, the database is queried.
 * The function requires a database connection.
 * The function returns an array of information, including:
 * - a TRUE/FALSE variable indicating success
 * - an array of either errors or the database result
 */
function check_login($dbc, $email = '', $pass = '') {

    $errors = []; // Initialize error array.

    // Validate the email address:
    if (empty($email)) {
        $errors[] = 'You forgot to enter your email address.';
    } else {
        $e = mysqli_real_escape_string($dbc, trim($email));
    }

    // Validate the password:
    if (password_verify($p, $row['pass'])) {
        $errors[] = 'You forgot to enter your password.';
    } else {
        $p = mysqli_real_escape_string($dbc, trim($pass));
    }

    if (empty($errors)) { // If everything's OK.

        // Retrieve the user_id and first_name for that email/password combination:
        $q = "SELECT user_id, first_name, pass FROM users WHERE email='$e'";
        $r = @mysqli_query($dbc, $q); // Run the query.

        // Check the result:
        if (mysqli_num_rows($r) == 1) {

            // Fetch the record:
            $row = mysqli_fetch_array($r, MYSQLI_ASSOC);

            // Return true and the record:
            return [true, $row];

        } else { // Not a match!
            $errors[] = 'The email address and password entered do not match those on file.';
        }

    } // End of empty($errors) IF.

    // Return false and the errors:
    return [false, $errors];

} // End of check_login() function.

Link to comment
Share on other sites

  • 2 years later...

Hey,

I notice this thread is from 2018, but I can't seem to find any other information on it -- just let me know if I should make a new thread. Basically, I'm having the exact same problem as the OP from 2018 -- I've worked through ch. 13, and can add/register a new user by using the 13.7 password_hash() function. I've checked in phpMyAdmin and can see the new user, the hashed password, etc. I can also update the user from the edit page as well. For reference, I'm on PHP Version 7.4.12. Basically, when trying to do the login function from 13.8, I keep getting 'Error - the email address and password do not match what we have on file.' I've tested this with a few different usernames and pw's, and can assure the passwords are correct, but I keep getting the error. I've also tested the error reporting, and can say for certain the error is not being thrown by the if/else statement here:

if (mysqli_num_rows($r) == 1) 

......


} else { //Not a match
            $errors[] = 'The email testing address and password entered do not match those on file.';

But rather, the error is coming from here:

 if (password_verify($p, $row['pass'])) {
                unset($row['pass']);
                return [true, $row];
            } else {
                $errors[] = 'The email testing2 address and password entered do not match those on file.';
            }

So, in the book, I noticed on the text of pg. 455 (5th edition) that it says to input this:

$q = "SELECT user_id, first_name, pass FROM users WHERE email='$e'";

however in the visual examples, it says to use this code, which is also how the file on github has the code for 13.8 as well:

$q = "SELECT user_id, first_name FROM users WHERE email='$e'";

I've tried running the code both with and without the 'pass' value in the SELECT function, but I keep getting the error. I'll post my code below, but basically, I'm just trying to see if there's a definite answer for what I'm doing wrong. In the thread above, someone mentioned needing the 'pass' and it makes sense, but there's conflicting information between the book elements, github, and the prior post. For reference, I've also compared my .php file to the 13.8 file on github, but can't seem to find the mistake I'm making on this one.

One last note, I also tried commenting out the code from 'unset($row['pass'])) to see if that would help, but that also does not seem to be causing the issue. Here's my code as of now:

<?php #Script 12.2 - login_functions.inc.php 

function redirect_user($page = 'index.php') {
    //start defining the URL... 
    //URL is http:// plus the host name plus the current directory:
    $url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']);

    //remove any trailing slashes:
    $url = rtrim($url, '/\\');

    //Add the page:
    $url .= '/' . $page;

    //Redirect the user:
    header("location: $url");
    exit(); //Quit the script. 

} //End of redirect_user function. 

function check_login($dbc, $email = '', $pass = '') {
    $errors = []; //Initialize error array

    if (empty($email)) {
        $errors[] = 'You forgot to enter your email address.';
    } else {
        $e = mysqli_real_escape_string($dbc, trim($email));
    }

    if (empty($pass)) {
        $errors[] = 'You forgot to enter your password.';
    } else {
        $p = trim($pass);//$p = mysqli_real_escape_string($dbc, trim($pass));
    }

    if (empty($errors)) {
        $q = "SELECT user_id, first_name, pass FROM users WHERE email='$e'";
        $r = mysqli_query($dbc, $q);

        if (mysqli_num_rows($r) == 1) {
            $row = mysqli_fetch_array($r, MYSQLI_ASSOC);

            if (password_verify($p, $row['pass'])) {
                unset($row['pass']);
                return [true, $row];
            } else {
                $errors[] = 'The email testing2 address and password entered do not match those on file.';
            }
            //return [true, $row];
        } else { //Not a match
            $errors[] = 'The email testing address and password entered do not match those on file.';
        }

    } //End of empty($errors) IF

    return [false, $errors];

} //End of check_login function.

I really appreciate your help on this. Chapter 14 has been great so far, I just wanted to see if I could get some clarity on this matter before I forget about the issue coming up. 

 

Thanks Again in Advance!

Link to comment
Share on other sites

Yes, there's a typo there that's my fault--sorry!--in that you should be selecting the password from the database, too. 

You have that in place in your code now. From your debugging work it seems that 

if (password_verify($p, $row['pass'])) {

is returning false. That means the problem is either with $p or with $row['pass']. I would start by registering a new user with a new password--just "password"--and testing that, just to rule out that you haven't mistakenly used the wrong password (i.e., the code is actually working properly!). I'd also print out the value of password_hash('your password') and make sure that entire value is being stored in the database (using phpMyAdmin or the like). 

Link to comment
Share on other sites

 Share

×
×
  • Create New...