In this video tutorial I create an extremely secure PHP Login Script. If you didn’t watch part 20 of this tutorial, you should check it out to find out how to use PHP Sessions and Cookies.
To make this login secure I added all of the following security features:
Keep all user information stored on the server with Sessions
Run all input through very strict Regular Expressions
Regenerate a new session token every time the user updates sensitive information
I add a few additional tricks along the way. All of the code follows the video. If you have any ideas on how I could improve this script pass them along.
Code From the Video
Goodlogin.php Script
<?php
// Initialize a session.
session_start();
require_once(“./includes/confighamdb.php”);
?>
<?php
if (isset($_POST[‘submitted’])) { // Check if the form has been submitted.
if (preg_match (‘%^[A-Za-z0-9]\S{8,20}$%’, stripslashes(trim($_POST[‘userid’])))) {
$u = escape_data($_POST[‘userid’]);
} else {
$u = FALSE;
echo ‘<p><font color=”red” size=”+1″>Please enter a valid User ID!</font></p>’;
}
// FIX IT Check for a good password
if (preg_match (‘%^[A-Za-z0-9]\S{8,20}$%’, stripslashes(trim($_POST[‘pass’])))) {
$p = escape_data($_POST[‘pass’]);
} else {
$p = FALSE;
echo ‘<p><font color=”red” size=”+1″>Please enter a valid Password!</font></p>’;
}
// FIX IT PHP Code for the CAPTCHA System
$captchchk = 1;
require_once(‘./includes/recaptchalib.php’);
$privatekey = “privatekey”;
$resp = recaptcha_check_answer ($privatekey,
$_SERVER[“REMOTE_ADDR”],
$_POST[“recaptcha_challenge_field”],
$_POST[“recaptcha_response_field”]);
if (!$resp->is_valid) {
// What happens when the CAPTCHA was entered incorrectly
Thank you for this! How do we get it on our website? I am currently making a site on Weebly. I put a custom HTML box in it and tried copy/pasting your script in but it isn’t showing up right. Can you help me? Thanks! 🙂
What I always do when I get an error is to print out to screen all of the values for each variable. I then check to make sure they have the correct values.
Since you copied the code though I’m guessing there is a problem with the database. Check to make sure every value is of the correct type in the database.
For the users I have the database set up this way
user_id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| lang_id | tinyint(3) unsigned | NO | | NULL | |
| time_zone | varchar(30) | NO | | NULL | |
| username | varchar(30) | NO | UNI | NULL | |
| pass | char(40) | NO | | NULL | |
| email | varchar(60) | NO | UNI | NULL |
Great tutorial…
I appreciate the effort you take to made such a good tutorial
BUT
After the login button pressed,the reCaptcha system returns an error says “Could not open socket”.I tried many methods posted in different blogs.But none of them works for me.Why did this happens?
That’s strange. I don’t have the problem with my code even without the change on any browser. There must be a typo in your code somewhere. Did you download the code from my site or did you copy it from the page?
I have not yet added this to my website, but it is the best one that I have found on the internet. I need a login system that will only allow logged in users to view all areas of my website.
will this system work?
First of All, Thankyou for all these great tutorials.
I have been following your videos for quiet a time now. I must admit that i learned jquery, wordpress, html, css and almost everything out there by watching your videos.
I’m very happy that the tutorials helped you 🙂 It was always my dream to be able to provide a free education to all that wished to take the time to learn.
I have many more tutorials planned. I’ll finish up programming and then move on to electronics, mathematics, physics, etc.
Thanks for taking the time to show your appreciation
$query = “SELECT user_id, first_name, last_name, email, userid, pass FROM users WHERE userid=’$u’ AND pass=SHA(‘$p’)”;
$result = mysql_query ($query) or trigger_error(“Either the Userid or Password are incorrect”);
if (mysql_affected_rows() == 1) { // A match was made….
After a SELECT shouldn’t you be using
if (mysql_num_rows() == 1)
On my server mysql_affected_rows() always returns zero after a SELECT.
I suspect it is because with a SELECT no existing rows are affected, whereas with an UPDATE, DELETE or INSERT the database is modified and rows are affected. A SELECT affects nothing.
I have been looking websites on Google.com for website security tips and found your website and found your secure user login tutorial. can you guide me how to check vulnerabilities in my website and how i can over come them. is there any plan for cover with taking some example website and show step by step how to secure the site.
You are very good and i hope you consider my request too.
Take a look at my PHP Security tutorials. I cover pretty much everything in them. All together I cover
SQL Injection
Cross Site Scripting (XSS)
Malicious Code Encoding
Session Hijacking
Session Fixation
Malicious System Calls
Buffer Overflows
Hey there!
First of all, you have really nice tutorials.
And I would like to know how the code would be if I wanted to log in with an email instead of a username.
I get confused where it says userid. I don’t know if it’s the username(userid) in some parts or the indexed user id(user_id) so I’m not sure which ones to change.
You can use either a userid or an email address. All you’ll need to change is to replace the useid regular expression test with the already provided email regular expression test. Does that answer your question?
Thanks for taking the time to put this comprehensive working tut together. It was immensely helpful for me get all my own thoughts to crystallize & to have a framework concept to start with. I would only add the following to your superb design: in searching for secure login ideas I have also come across using a salt with the hash for certain security vectors. Here is a good how to: http://crackstation.net/hashing-security.html It integrated easily enough with all the concepts you put together. sha256 is now available & I used it for the hashing. Another resource that might be good for all of us to use is OWASP (Open Web Application Security Project) site for php: http://code.google.com/p/owasp-esapi-php/
The OWASP home is https://www.owasp.org/index.php/Main_Page
I’m glad ou liked it. Thanks for pointing out all of the additional resources. I should update tutorials, but after I finish them I don’t often go back
I am adding a portion to our website and they have asked if we can create a login that allows our employees to login and use it like a base-camp, not sure if you know what that is but it allows use to keep track of projects.
First of all, thanks for these great tutorials, they are very useful. I’ve given them a load of thumbs up on youtube, keep up the good work.
I have coded up the login scripts and it’s all working great until the the point where I reach the index.php page. Then nothing happens – I don’t get the options to logout etc (or anything in fact). Should my index.php file have anything in it? Or should it be written to by the login.php file as appears to happen in your video?
I might be missing something here, but it seems like most of the php scripting part of login.php should be hidden away in a private folder. Is that correct?
Hey, I’ve sorted the index.php script, I should have been more patient, it was all in the next video!
Unfortunately I have a new problem, my header $_SESSION[‘token_id’] doesn’t seem to survive the transfer to the new index.php page once the user has logged in. Any hints as to why would be much appreciated, thanks!
hello, sir i want to start a new garments business retail shop of garments so am looking for a very outstanding logo….. normally on net thre was a basic logo of garments will u give a best one ??
Thanks for your great tutorials. But I have some questions
regarding “passing password information in encrypted form”.
Usually, in login system, we use two files to handle that.
First is index.php (that contains the form),
and the second is the php file that collect & process variables
from the index.php (, which is goodlogin.php, in your tutorial).
In the form (index.php), password is stored in the “pass” variable.
And it is SENT to the server, and then processed by the goodlogin.php
by the $_POST method.
We see that the password is sent to the server BEFORE it is encrypted.
And someone could steal the $pass variable.
So I think I haven’t seen your method in “passing password information
in encrypted form”.
Can you give me the way in doing that ?
Since I would like to encrypt the password before it was sent to server.
Thank you Imam 🙂 I use the Zend framework for authentication in a login system, but I haven’t had time to cover that topic yet. Here is a pretty good tutorial on how that is done. I’ll do my best to cover Zend as soon as possible
I have gone through the secure login tutorial and understood most of it except one small bit that is regarding the tokenID, specifically the line
$tokenId = rand(10000, 9999999);
whose value you update into the DB & you call this as the second layer of security. I am unable to understand how this tokenID is helping in security? I mean I don’t see where this value is being called up and checked for any identification.
Could you please explain its relevance by pointing out its usage in the program.
You’re very welcome 🙂 I’m glad you found them useful. I continue writing that program in the tutorials that follow. Sorry that I didn’t make that clear. I hope to update this information soon when I cover the Zend framework which is what I have been using for the past couple years.
Thanks for all this information.
You’re very welcome. Glad to help 🙂
Thank you for this! How do we get it on our website? I am currently making a site on Weebly. I put a custom HTML box in it and tried copy/pasting your script in but it isn’t showing up right. Can you help me? Thanks! 🙂
Sorry to create a secure login system you need to have a database. As far as I can tell weebly doesn’t provide database access or creation.
I am working with the godlogin.php file. I have it working up to this point:
$query = “SELECT user_id, first_name, last_name, email, pass FROM users_tbl WHERE user_id=’$u’ AND pass=SHA(‘$p’)”;
I feel this is correct since the next line:
$result = mysql_query ($query) or trigger_error(“Either the Userid or Password are incorrect”);
Does not trigger the error.
I have used register2.php from the root of the zip file to enter the data into the database. Everything seems to be there.
Any suggestions on what I should try?
What I always do when I get an error is to print out to screen all of the values for each variable. I then check to make sure they have the correct values.
Since you copied the code though I’m guessing there is a problem with the database. Check to make sure every value is of the correct type in the database.
For the users I have the database set up this way
user_id | mediumint(8) unsigned | NO | PRI | NULL | auto_increment |
| lang_id | tinyint(3) unsigned | NO | | NULL | |
| time_zone | varchar(30) | NO | | NULL | |
| username | varchar(30) | NO | UNI | NULL | |
| pass | char(40) | NO | | NULL | |
| email | varchar(60) | NO | UNI | NULL |
I hope that helps?
When I run the goodlogin.php should I be able to look in the database and see something in the token row?
I found my issue. I thought it was a good idea to limit the password to 20 characters. Then I realized that SHA requires 40 characters.
I will work some more on this.
Yes that would be a problem. I figured that might be it
Great tutorial…
I appreciate the effort you take to made such a good tutorial
BUT
After the login button pressed,the reCaptcha system returns an error says “Could not open socket”.I tried many methods posted in different blogs.But none of them works for me.Why did this happens?
It seems that there is a problem with the captcha system with some fedora browsers. Here is the fix
Replace
define(“RECAPTCHA_VERIFY_SERVER”, “api-verify.recaptcha.net”);
With this
define(“RECAPTCHA_VERIFY_SERVER”, gethostbyname(‘api-verify.recaptcha.net’));
In my recaptcha file,it’s like,
define(“RECAPTCHA_API_SERVER”, “http://www.google.com/recaptcha/api”);
define(“RECAPTCHA_API_SECURE_SERVER”, “https://www.google.com/recaptcha/api”);
define(“RECAPTCHA_VERIFY_SERVER”, “www.google.com”);
So,i changed last line in to
define(“RECAPTCHA_VERIFY_SERVER”, gethostbyname(‘www.google.com’));
But
Same Error……
That’s strange. I don’t have the problem with my code even without the change on any browser. There must be a typo in your code somewhere. Did you download the code from my site or did you copy it from the page?
I have not yet added this to my website, but it is the best one that I have found on the internet. I need a login system that will only allow logged in users to view all areas of my website.
will this system work?
It is very secure, but because of legal reasons I can’t guarantee it is perfect
First of All, Thankyou for all these great tutorials.
I have been following your videos for quiet a time now. I must admit that i learned jquery, wordpress, html, css and almost everything out there by watching your videos.
Keep up the good work. Best Wishes for future
I’m very happy that the tutorials helped you 🙂 It was always my dream to be able to provide a free education to all that wished to take the time to learn.
I have many more tutorials planned. I’ll finish up programming and then move on to electronics, mathematics, physics, etc.
Thanks for taking the time to show your appreciation
After a SELECT shouldn’t you be using
if (mysql_num_rows() == 1)
On my server
mysql_affected_rows()
always returns zero after a SELECT.Sorry that line should have said:
if (mysql_num_rows($result) == 1)
I’m not sure what the problem might be? mysql_affected_rows works or me
I suspect it is because with a SELECT no existing rows are affected, whereas with an UPDATE, DELETE or INSERT the database is modified and rows are affected. A SELECT affects nothing.
Yes that is why it isn’t working. Sorry I didn’t have the time to figure that out
I have been looking websites on Google.com for website security tips and found your website and found your secure user login tutorial. can you guide me how to check vulnerabilities in my website and how i can over come them. is there any plan for cover with taking some example website and show step by step how to secure the site.
You are very good and i hope you consider my request too.
Keep up the good work. Best Wishes for future
Take a look at my PHP Security tutorials. I cover pretty much everything in them. All together I cover
SQL Injection
Cross Site Scripting (XSS)
Malicious Code Encoding
Session Hijacking
Session Fixation
Malicious System Calls
Buffer Overflows
Hey there!
First of all, you have really nice tutorials.
And I would like to know how the code would be if I wanted to log in with an email instead of a username.
I get confused where it says userid. I don’t know if it’s the username(userid) in some parts or the indexed user id(user_id) so I’m not sure which ones to change.
I hope it’s clear.
Thanks!
You can use either a userid or an email address. All you’ll need to change is to replace the useid regular expression test with the already provided email regular expression test. Does that answer your question?
Thanks for taking the time to put this comprehensive working tut together. It was immensely helpful for me get all my own thoughts to crystallize & to have a framework concept to start with. I would only add the following to your superb design: in searching for secure login ideas I have also come across using a salt with the hash for certain security vectors. Here is a good how to: http://crackstation.net/hashing-security.html It integrated easily enough with all the concepts you put together. sha256 is now available & I used it for the hashing. Another resource that might be good for all of us to use is OWASP (Open Web Application Security Project) site for php: http://code.google.com/p/owasp-esapi-php/
The OWASP home is https://www.owasp.org/index.php/Main_Page
I’m glad ou liked it. Thanks for pointing out all of the additional resources. I should update tutorials, but after I finish them I don’t often go back
I am adding a portion to our website and they have asked if we can create a login that allows our employees to login and use it like a base-camp, not sure if you know what that is but it allows use to keep track of projects.
Hey,
First of all, thanks for these great tutorials, they are very useful. I’ve given them a load of thumbs up on youtube, keep up the good work.
I have coded up the login scripts and it’s all working great until the the point where I reach the index.php page. Then nothing happens – I don’t get the options to logout etc (or anything in fact). Should my index.php file have anything in it? Or should it be written to by the login.php file as appears to happen in your video?
I might be missing something here, but it seems like most of the php scripting part of login.php should be hidden away in a private folder. Is that correct?
Any hints would be much appreciated. Thanks,
Michael
I’m sorry you are having trouble. I put every script in one zipped archive on this page PHP Video Tutorial. I hope that helps
Hey, I’ve sorted the index.php script, I should have been more patient, it was all in the next video!
Unfortunately I have a new problem, my header $_SESSION[‘token_id’] doesn’t seem to survive the transfer to the new index.php page once the user has logged in. Any hints as to why would be much appreciated, thanks!
* EDIT: I meant $_SESSION[‘first_name’] and $_SESSION[‘userid’]
Thanks!
hello, sir i want to start a new garments business retail shop of garments so am looking for a very outstanding logo….. normally on net thre was a basic logo of garments will u give a best one ??
Why not just buy a simple cheap logo from a place like iStockPhoto? Something like this http://www.istockphoto.com/search/text/sewing/source/basic#19a90100
I also cover the process of making your own logo and a bunch of samples here as well Make your own logo
Dear Derek Banas,
Thanks for your great tutorials. But I have some questions
regarding “passing password information in encrypted form”.
Usually, in login system, we use two files to handle that.
First is index.php (that contains the form),
and the second is the php file that collect & process variables
from the index.php (, which is goodlogin.php, in your tutorial).
In the form (index.php), password is stored in the “pass” variable.
And it is SENT to the server, and then processed by the goodlogin.php
by the $_POST method.
We see that the password is sent to the server BEFORE it is encrypted.
And someone could steal the $pass variable.
So I think I haven’t seen your method in “passing password information
in encrypted form”.
Can you give me the way in doing that ?
Since I would like to encrypt the password before it was sent to server.
Thanks before.
Regards,
Imam Wahyudi.
Thank you Imam 🙂 I use the Zend framework for authentication in a login system, but I haven’t had time to cover that topic yet. Here is a pretty good tutorial on how that is done. I’ll do my best to cover Zend as soon as possible
Can you please help me here, this is not working for me..
Why does here the action is referring to the same page?
Your tutorials are great. I have learned alot from you.
Thanking you in advance.
What errors are you getting?
Hi Derek,
I have gone through the secure login tutorial and understood most of it except one small bit that is regarding the tokenID, specifically the line
$tokenId = rand(10000, 9999999);
whose value you update into the DB & you call this as the second layer of security. I am unable to understand how this tokenID is helping in security? I mean I don’t see where this value is being called up and checked for any identification.
Could you please explain its relevance by pointing out its usage in the program.
Thanks for the overall wonderful Tutorial.
Hi Ajay,
You’re very welcome 🙂 I’m glad you found them useful. I continue writing that program in the tutorials that follow. Sorry that I didn’t make that clear. I hope to update this information soon when I cover the Zend framework which is what I have been using for the past couple years.