Listed under PHP & MySQL
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 (14 Aug 2008): Moved database connection details to config.php file. Edit config.php file to specify your own database connection details.
Update (05 Feb 2008): Fixed a bug in the registration form.
Update: A simple registration form has been added to the download package.
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 makes the application easier to manage when the application logic gets more complex.
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.
Jatinder,
Great script thanks for sharing. Just a question regarding the storing of database access credentials in a separate php page as apposed to how you have it in your exec pages? Is there any real benefit or standard here?
Thanks.
[Thomas]
There are absolutely no benefits in storing access details in the exec pages. The only reason I did that was to keep the script as simple as possible because it is targeted at PHP newbies.
In fact I have advocated the use of PHP includes in another of my articles.
But recently I have received a number emails from users asking me how to change the database connection details. Therefore I have moved the connection details to a separate config.php file.
Thanks for the awesome code. It was easy to adapt for use with my existing singleton database connection class. I disagree with your opinion on having separate form/code files, I think you’ll do better to make them all in one, especially for the purpose of a tutorial. I may be a new PHP developer, so there could be a thousand people yelling differently. I do however encourage separate files for classes, and I wish I had seen more object-oriented application here.
Hi there, is it possible to log the user out when a tab/ window is closed?
Thanks
@Michael Norris
The login script is using temporary cookies. That is, the session should expire as soon as you close the browser.
However, if the session persists for you even after restarting the browser, please check your “session.cookie_lifetime” setting.
I noticed something odd. You sanitize all user supplied values, but in the sql query you don’t use the sanitized version $password, but you use $_Post[’$password’]
@MrFrans
We will be converting $_POST[’$password’] into a md5 hash. Therefore we don’t need to sanitize it.