Login and user authentication is the most common feature in any dynamic website. Before we go any further, Download the PHP Login Script. The zip file contains the complete PHP source code of our authentication script and a SQL file to create and populate the required tables. Download the file, extract its contents and run the SQL file to create the members table.
Update: A simple registration form has been added to the download package.
Update (05 Feb 2008): Fixed a bug in the registration form.
login-form.php page simply contains a form with two fields: login and password, and should be self-explanatory in what it does. login-exec.php script is where all the action is.
PHP Tip : Always try to keep the form and the submission/action page separate. Unless necessary, don’t make pages post information to themselves. I normally append “form” to pages containing the form and append “exec” to the page which handles the submission. This helps me in managing the application as the number of PHP scripts grow.
Lets go through the code step by step. In the first few lines of login-exec.php, we simply start a session and open a connection to mysql database.
In the simplest case, special characters may simply break your query. In a more extreme case, a hacker might use SQL injections to gain access to your application. So it is important that we escape these special characters with a \ (backslash). That is, insert a backslash before each special character.
We can escape special characters (prepend backslash) using mysql_real_escape_string or addslashes functions. In most cases PHP will this do automatically for you. But PHP will do so only if the magic_quotes_gpc setting is set to On in the php.ini file. We first check whether this setting is on or not. If the setting is off, we use mysql_real_escape_string function to escape special characters. If you are using PHP version less that 4.3.0, you can use the addslashes function instead.
A MySQL connection is required before using mysql_real_escape_string() otherwise an error of level E_WARNING is generated.
If the magic quotes setting is on, we do not need escape special characters since PHP has already done it for us. We can check the magic_quotes_gpc by using get_magic_quotes_gpc function.
<?php if(!get_magic_quotes_gpc()) { $login=mysql_real_escape_string($_POST['login']); }else { $login=$_POST['login']; } ?>
You can use the function below to clean and prepare data for queries. The function goes through the following steps:
<?php function clean($str, $encode_ent = false) { $str = @trim($str); if($encode_ent) { $str = htmlentities($str); } if(version_compare(phpversion(),'4.3.0') >= 0) { if(get_magic_quotes_gpc()) { $str = stripslashes($str); } if(@mysql_ping()) { $str = mysql_real_escape_string($str); } else { $str = addslashes($str); } } else { if(!get_magic_quotes_gpc()) { $str = addslashes($str); } } return $str; } ?>
Next we formulate the query which will test whether a user with this login and password exists.
Note that we are not storing passwords in the database as plain text. Instead we are storing the md5 hash of the password. Use md5 function to create a 32 character hash of any string. md5 is one way encryption. That is, once the password is encrypted, there is no way to decrypt it.
So if a md5 hash can not be decrypted, how do we compare the user submitted password with the one in the database? The answer is that we simply generate a md5 hash of the user submitted password and then compare this hash to the one stored in the database.
<?php $qry="SELECT member_id FROM members WHERE login='$login' AND passwd='".md5($_POST['password'])."'"; $result=mysql_query($qry); ?>
The query will return a result set with a single row if the login details are correct and zero rows if the login details are incorrect. Use mysql_num_rows to find out the number of rows in the result set and hence determine whether the login details were correct or not.
Once we know that the login details are correct, we need to store this information somewhere, so that the subsequent pages know that the user has been authenticated successfully. We use PHP session for this purpose.
Retrieve the member’s ID from the result set and store it in the session as SESS_MEMBER_ID. Subsequent pages will just need to test for the existence of SESS_MEMBER_ID in the session to verify the authentication status of the user. After storing the member ID in the session, redirect the user to the member-index.php page.
<?php if(mysql_num_rows($result)>0) { //Login Successful //Regenerate session ID to //prevent session fixation attacks session_regenerate_id(); $member=mysql_fetch_assoc($result); $_SESSION['SESS_MEMBER_ID']=$member['member_id']; //Write session to disc session_write_close(); header("location: member-index.php"); exit(); } ?>
If the login fails, redirect the user to login-failed.php page.
Once we have ascertained that the user supplied login details are correct, we store his ID in a session variable named SESS_MEMBER_ID. But we before we do that, we call the session_regenerate_id() function. This function generates a new session ID while keeping intact any information stored in the session.
As mentioned above, the presence or absence of SESS_MEMBER_ID in the session will tell us whether the user is logged in or not. If a variable names SESS_MEMBER_ID exists in the session, then the user has been logged in and authenticated. I have moved this logic to a separate PHP script, auth.php
<?php //Start session session_start(); //Check whether the session variable //SESS_MEMBER_ID is present or not if(!isset($_SESSION['SESS_MEMBER_ID']) || (trim($_SESSION['SESS_MEMBER_ID'])=='')) { header("location: access-denied.php"); exit(); } ?>
Now we can just include the auth.php file in any page we want to password protect. See member-index.php and member-profile.php page for examples.
To logout the user, simply unset the SESS_MEMBER_ID variable. See the logout.php script for example.
<?php //Start session session_start(); //Unset the variable SESS_MEMBER_ID stored in session unset($_SESSION['SESS_MEMBER_ID']); ?>
Download the Login Script to get the full source code for the above examples.
Here is a brief description of the main files:
Comments
This is a nice collection of scripts. I’ve been searching for some good authentication code and of all the scripts I’ve seen that support password encryption and guard against hack attacks, this is the easiest to understand, the most concise, and the easiest to adapt and deploy. Thanks – very useful, and you’ve saved me writing a system from scratch.
I have been trying to put a Members Only area on my website to no avail. This script is so easy to understand and implement. Thank you so much for this.
Thank you very much for this script! I’ve been trying to find one that works! And this actually works! Thanks!
Thanks you for this script ill definitely use this one!
J! thanks alot for this script – really saved me from all hustle to get me project running! This is definitly a good work.
B
That is an amazing code. I have been around to many, many different sites and couldn’t get one that worked as easy and as well as yours. The only thing that I was trying to do was view the entered password, but…what would be the point of such a secure script if you are going to make the password unprotected…very very well done!!!!
wonderful script, i like it very much, please provide some more new scripts in php mysql.
thank you very much for the script
I am a php/mysql nub. How do I make it so member-index.php displays user information, ie, “Welcome, [firstname]”?
Adelevie, you can store user information like name or email in the session and then retrieve this information later on in other pages.
Take a look at login-exec.php script, line 33. I am storing the user’s member_id (primary key) in the session.
$_SESSION[‘SESS_MEMBER_ID’]=$member[‘member_id’];
You can store values from other database columns as well using the same syntax. To learn more about using sessions, please read PHP Sessions Tutorial
Hello, another newbie here.
When I use your register-form, it returns with a “First name missing”, “Last name missing” and so on.
I removed the check from reg-exec, and without it, it does actually register with empty fields.
Any idea what I might be doing wrong?
Would it be possible to also include a, “I forgot my password” script?
Casper,
Thank you for pointing out the bug. You can download the updated script from the download link in the article above.
I almost never feel the urge to post comments… but I just had to acknowledge your work. I gotta say I am impressed with the simplicity and functionality of your scripts. The code is very clean. Nice work for sure(and i’m sure you can do much more complex coding than this)… you get three claps from me.
How can I get the script if somebody forgets the password? Can it be send to user via email or simply reseted?
Awesome script. I have one quick question: Is there a simple way I can have three individual private member areas? For example, if a user is a student they are redirected to private1.php, a teacher, they go to private2.php and an administrator to private3.php?
I’d like it so nobody can see any page but there own (students cannot see teacher or admin pages).
Thanks so much!
Can anyone offer a Forgot Password script to work with this login? That would be great.
Thanks for the brilliant scripts and tutorial. Got this up and running withing 24hrs and thats from someone with no previous php/mysql knowledge.
I am also now trying to work out how I can have client specific areas after the login. Although I’m thinking that Will ^^ could add an additional id to his db that he could assign a number that corresponds with each tier of pages that can be accessed?
[Will]
I have received a number of requests for “Forgot Password” feature. I will add this feature as soon as I get some time to update this script.