1. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    Yep.

    As to the query itself, note that phpmyadmin (which generated it) creates a lot of syntax noise. For example, when the character encoding and the collation is already set at table level, it's useless to repeat the same settings for every column. Usually you just set the whole database to UTF-8, and that's it. Explicitly setting AUTO_INCREMENT and those ugly backticks also aren't necessary. So the whole query could be boiled down to

    Code:
    CREATE TABLE users (
      id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
      username varchar(255) NOT NULL UNIQUE,
      password char(60) NOT NULL,
      email varchar(255) NOT NULL UNIQUE
    ) ENGINE=InnoDB
    ;
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  2. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    436
    Rep Power
    8
    ok weird, I have made the adjustments, but when I register and try to log in, I get the 'login failed'... here is the login script (I suspect the problem will be there because I can see the password encrypted in PhpMyAdmin and it has 60 symbols so I think the register.php is correct...):

    PHP Code:
    <?php 

        
    // First we execute our common code to connection to the database and start the session 
        
    require("common.php"); 
        require(
    "lib/password.php"); 
        
    // This variable will be used to re-display the user's username to them in the 
        // login form if they fail to enter the correct password.  It is initialized here 
        // to an empty value, which will be shown if the user has not submitted the form. 
        
    $submitted_username ''
         
        
    // This if statement checks to determine whether the login form has been submitted 
        // If it has, then the login code is run, otherwise the form is displayed 
        
    if(!empty($_POST)) 
        { 
            
    // This query retreives the user's information from the database using 
            // their username. 
            
    $query 
                SELECT 
                    id, 
                    username, 
                    password, 
                    email 
                FROM users 
                WHERE 
                    username = :username 
            "

             
            
    // The parameter values 
            
    $query_params = array( 
                
    ':username' => $_POST['username'
            ); 
             
            try 
            { 
                
    // Execute the query against the database 
                
    $stmt $db->prepare($query); 
                
    $result $stmt->execute($query_params); 
            } 
            catch(
    PDOException $ex
            { 
                
    // Note: On a production website, you should not output $ex->getMessage(). 
                // It may provide an attacker with helpful information about your code.  
                
    die("Failed to run query: " $ex->getMessage()); 
            } 
             
            
    // This variable tells us whether the user has successfully logged in or not. 
            // We initialize it to false, assuming they have not. 
            // If we determine that they have entered the right details, then we switch it to true. 
            
    $login_ok false
             
            
    // Retrieve the user data from the database.  If $row is false, then the username 
            // they entered is not registered. 
            
    $row $stmt->fetch(); 
            if(
    $row
            { 
                
    // Using the password submitted by the user and the salt stored in the database, 
                // we now check to see whether the passwords match by hashing the submitted password 
                // and comparing it to the hashed version already stored in the database. 
            
    $hash password_hash($_POST['password'], PASSWORD_BCRYPT, array("cost" => 10));    

                 
    // $password comes from the login form, $hash comes from the database 

    if ( password_verify($hash$row['password']) )    // login successful 

         
    // If they do, then we flip this to true 
                    
    $login_ok true


            } 
             
            
    // If the user logged in successfully, then we send them to the private members-only page 
            // Otherwise, we display a login failed message and show the login form again 
            
    if($login_ok
            { 
                
    // Here I am preparing to store the $row array into the $_SESSION by 
                // removing the salt and password values from it.  Although $_SESSION is 
                // stored on the server-side, there is no reason to store sensitive values 
                // in it unless you have to.  Thus, it is best practice to remove these 
                // sensitive values first. 
                
    unset($row['password']); 
                 
                
    // This stores the user's data into the session at the index 'user'. 
                // We will check this index on the private members-only page to determine whether 
                // or not the user is logged in.  We can also use it to retrieve 
                // the user's details. 
                
    $_SESSION['user'] = $row
                 
                
    // Redirect the user to the private members-only page. 
                
    header("Location: private.php"); 
                die(
    "Redirecting to: private.php"); 
            } 
            else 
            { 
                
    // Tell the user they failed 
                
    print("Login Failed."); 
                 
                
    // Show them their username again so all they have to do is enter a new 
                // password.  The use of htmlentities prevents XSS attacks.  You should 
                // always use htmlentities on user submitted values before displaying them 
                // to any users (including the user that submitted them).  For more information: 
                // http://en.wikipedia.org/wiki/XSS_attack 
                
    $submitted_username htmlentities($_POST['username'], ENT_QUOTES'UTF-8'); 
            } 
        } 
         
    ?> 
    <html>
    <body>


    <form action="login.php" method="post"> 
        Username: 
        <input type="text" name="username" value="<?php echo $submitted_username?>" /> 
        <br /><br /> 
        Password:
        <input type="password" name="password" value="" /> 
        <br /><br /> 
        <input type="submit" value="Login" /> 
    </form> 
    <a href="register.php">Register</a>
    </body>
    </html>
  3. --
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Jul 2012
    Posts
    3,959
    Rep Power
    1014
    There's a misunderstanding. password_hash() and password_verify() work on their own, you do not call them together. That's what I tried to explain in #128.

    Just look at the function names to see what they do:
    • password_hash($password, $algo, $options) creates a new hash to be stored in the database. You only call it when registering a new user or resetting the password (or in the rare case you need to rehash the passwords due to an algorithm change).
    • password_verify($password, $hash) checks if a (plaintext) $password matches a given $hash.


    Again: It's just one function call for each action. You do not need to hash a password yourself in order to check it. password_verify() takes care of all that.

    In fact, you cannot use password_hash() to check a password, because it creates a completely new hash with a new salt and possibly different algorithm options. So even if the original password is the same, the new hash doesn't match the old one, because the other parameters have changed.

    So remove the "$hash = password_hash(...)" line and just do

    PHP Code:
    if ( password_verify($_POST['password'], $row['password']) 
    {


    Last edited by Jacques1; April 13th, 2013 at 09:17 AM.
    The 6 worst sins of security ē How to (properly) access a MySQL database with PHP

    Why canít I use certain words like "drop" as part of my Security Question answers?
    There are certain words used by hackers to try to gain access to systems and manipulate data; therefore, the following words are restricted: "select," "delete," "update," "insert," "drop" and "null".
  4. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    436
    Rep Power
    8
    when I try to hash the token (password recovery) then I get an error:

    Fatal error: Call to undefined function password_hash()

    on this line:

    PHP Code:
    $password_token rnum();
     
    $hash password_hash($password_tokenPASSWORD_BCRYPT, array("cost" => 10)); 
    -----

    "update"

    I forgot not my password, but the require on top of the page to get the algorithm etc... it now is resolved!
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    15
    Rep Power
    0

    Thumbs up Forgot Password * OPTION anyone??


    Primarily i would like to remark to respectable author/authors of this work-of-art in the clear code description throughout the provided php matter.

    I'm working on a personal project, part of my thesis on medical prescriptions based on sql and php. What caught my interest is that a password reset / forgot password option isn't available which I believe to unfairly compromise the code's real-use in its totality.

    has anyone tried this before with this code? there are ways available after thorough researching online but these happen to tackle other means of encryption rather than the one used here, which I happen to have fallen in love with heh

    cheers,
    Ian
  6. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    436
    Rep Power
    8
    hi Ian, read the previous page, there I gave it a try to make a forgot password and I'm almost done. Also there are some tips to make it easier such as using a library
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    15
    Rep Power
    0

    Question


    Originally Posted by derplumo
    hi Ian, read the previous page, there I gave it a try to make a forgot password and I'm almost done. Also there are some tips to make it easier such as using a library
    Thanks man for sharing, very respectable of yourself! AND the authors

    I see that the code jacques1 and E-OREO have shared regarding to reset option is 'ridiculously' simple, which is a very good thing, but it's not suggesting me where it should go and when?

    I've presumed to load a new page triggered by a forgot pw hyperlink from login.php. then code should run the new hash and overwrite existing pw in users and submit some token/privilege to user to use in entering new pw.

    Have you a definite outcome with what you've computated so far through the feedback you've received, so I'll might be able to utilise the code with my project?

    cheers everyone!
    how weird spending saturday nights programming haha!

    Ian
  8. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    436
    Rep Power
    8
    well, i'm almost done but don't expect too much, then you'll never be disappointed when it doesn't work (and VERY happy when it does )
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    15
    Rep Power
    0

    Question


    Cheers man for even replying back! I try to never expect anything from anyone kind-of-person, I'm more into doing-everything-myself and doing-it-for-others type of guy.

    but this happened to be in a field which I'm still a starter in...and so far in just couple of days have made leaps of progress so far thank to decent people over the internet especially within this thread.

    currently am at: Github

    will create password.php

    then instructions tell to hash and/or verify.
    I see that password.php has 'everything' within it so how can I call just these two parts hash and verify from it? sorry guys for inconveniencing! hope the world evolves on the sharing principle exercised over mature forums like this is.

    thanks again,
    Ian
  10. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    436
    Rep Power
    8
    hi Ian, look at understanding quote, (and asking for help is only a good thing, when you don't know something, you can only learn it)

    Originally Posted by Jacques1
    There's a misunderstanding. password_hash() and password_verify() work on their own, you do not call them together. That's what I tried to explain in #128.

    Just look at the function names to see what they do:
    • password_hash($password, $algo, $options) creates a new hash to be stored in the database. You only call it when registering a new user or resetting the password (or in the rare case you need to rehash the passwords due to an algorithm change).
    • password_verify($password, $hash) checks if a (plaintext) $password matches a given $hash.


    Again: It's just one function call for each action. You do not need to hash a password yourself in order to check it. password_verify() takes care of all that.

    In fact, you cannot use password_hash() to check a password, because it creates a completely new hash with a new salt and possibly different algorithm options. So even if the original password is the same, the new hash doesn't match the old one, because the other parameters have changed.

    So remove the "$hash = password_hash(...)" line and just do

    PHP Code:
    if ( password_verify($_POST['password'], $row['password']) 
    {


    and you can call password.php by including this line in your code:

    PHP Code:
    require("password.php"); 
    and when you have it in a folder you will get something like this:

    PHP Code:
    require("folder/password.php"); 
  11. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    436
    Rep Power
    8
    I've a problem with this code, it is the response code of the forgot password. It doesn't seem to turn the $response_auth true. Before you get here you'll have to enter your username and email on an other page, are those the same, an email is dispatched, if not, you don't know it but nothing happened... if all is good, the id and the token are stored in the database.

    PHP Code:
    <?php 

        
    // First we execute our common code to connection to the database and start the session 
        
    require("common.php"); 
        require(
    "lib/password.php");
         
        
    // This if statement checks to determine whether the login form has been submitted 
        // If it has, then the login code is run, otherwise the form is displayed 
        
    if(!empty($_POST)) 
        { 
     
    // This query retreives the user's information from the database using 
            // their username. 
            
    $query 
                SELECT 
                    response
                FROM responses
                WHERE 
                    id = :id
            "

             
            
    $query_params = array( 
                
    ':id' => $_POST['id'
            ); 
             
            try 
            { 
                
    // Execute the query against the database 
                
    $stmt $db->prepare($query); 
                
    $result $stmt->execute($query_params); 
            } 
            catch(
    PDOException $ex
            { 
                
    // Note: On a production website, you should not output $ex->getMessage(). 
                // It may provide an attacker with helpful information about your code.  
                
    die("Failed to run query: " $ex->getMessage()); 
            } 

            
    $row $stmt->fetch(); 
            
    $response_auth false;
             if ( 
    password_verify($_POST['response'], $row['response']) )
            {
               
    $response_auth true;
            }
            if(
    $response_auth
            { 
               
    $query 
        
                UPDATE users 
                SET 
                    password = :password
                WHERE
                    id = :id 
            "

                
          
    $hash password_hash($_POST['password'], PASSWORD_BCRYPT, array("cost" => 10));         
             
           
            
    // Here we prepare our tokens for insertion into the SQL query.  We do not 
            // store the original password; only the hashed version of it.  We do store 
            // the salt (in its plaintext form; this is not a security risk). 
            
    $query_params = array( 
                
    ':password' => $hash
                
    ':id' => $row['id']
            ); 
             
             
            try 
            { 
                
    // Execute the query against the database 
                
    $stmt $db->prepare($query); 
                
    $result $stmt->execute($query_params); 
            } 
            catch(
    PDOException $ex
            { 
                
    // Note: On a production website, you should not output $ex->getMessage(). 
                // It may provide an attacker with helpful information about your code.  
                
    die("Failed to run query: " $ex->getMessage()); 
            } 


            } 
        } 
         
    ?> <html>
    <body>                                  
    <form action="response_forgot_password.php" method="post"> 
        Response:
        <input type="text" name="response" value="" /> 
        <br /><br />
        Number:
        <input type="text" name="id" value="" /> 
        <br /><br /> 
     New password:
        <input type="text" name="password" value="" /> 
        <br /><br /> 
        <input type="submit" value="Login" /> 
    </form> 
    </body>
    </html>
  12. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    15
    Rep Power
    0

    Red face


    Originally Posted by derplumo
    hi Ian, look at understanding quote, (and asking for help is only a good thing, when you don't know something, you can only learn it)



    and you can call password.php by including this line in your code:

    PHP Code:
    require("password.php"); 
    and when you have it in a folder you will get something like this:

    PHP Code:
    require("folder/password.php"); 
    thanks man once again, I've been carefully reading the posts and the available info throughout, with the hope of acquiring a general understanding that I can implement in practice.

    What about the part of sending out the 'link' by mail to the user to enter their new pw?

    cheers man,
    sorry to bother again.

    Ian
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    15
    Rep Power
    0
    wow man, didn't see your earlier post! damn, sorry mate! ..am going to have a shot at it & keep you posted. Cheers mate!

    [EDIT] I presume you've created a response field in response database seeing your query. what's the role of the response field? so I'll create that same field within my USERS table.

    Also you're asking for number and ID, have these been generated earlier or if not what're they? I'm keeping in mind that you obviously have different scenario than mine, but when I ask questions like these I'm referring to the concept that we should share within both our implementations rather than the ancillaries.

    I had in mind that I'd only ask user to enter his/her username this is then compared and email dispatched... don't know how to send email, also if values have to be generated to be passed to the user via email for keying in, that also I don't tknow about.. then I presume comes your code, where through the link provided in the email the user must enter the number and ID..these are compared and if mathc password is changed...

    correct? any further links or code?

    Ian -MALTA
  14. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    436
    Rep Power
    8
    I will post it tonight or tomorrow, but the whole mail function is explained here somewhere... how is your project going? Doesn't matter man
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    15
    Rep Power
    0
    thankgod I'm doing really fine thanks to everyone's support.. just a database having patient info with doctor's prescription, multiple login one for doctors/general practitioners to fetch old prescriptions and issue new ones. and another login for pharmacists to access prescription online by searchign database using ptient ID. It's remarkably successful in concept as current paper-based systems which are unfortunately in effect in majority of countries are slow, subject to errors and suffer in fraud. In UK back in 2004 prescription fraud costed government around 80million GBP.. but this is irrelevant.. you know thesis and stuff...but to get u in the picture..

    now am working on this password reset thingy, will post tomorrow morning with updates.

    cheers everyone,
    Ian

IMN logo majestic logo threadwatch logo seochat tools logo