How to make secure login form with PHP and MySQL

by  
Share:
How to make secure login with PHP and MySQL

Login is one of the most common functionality you will come across. If you are not using any Content Management Tool (CMS) for your website then you have to code login section all by yourself be it admin login or user login. One should take necessary steps to make a secure login section preventing against SQL injection, data integrity and other malicious attacks. In this tutorial you will learn how to make a secure login with php and mysql database.

View Demo

Create a database named demos (you can change ofcourse ), then create a table users and add a row/data for user. Check the supported hashing algorithm using hash_algos(). I have used sha512 along with a salt that will make the password more secured. Check the custom function to generate a hash for each password.

<?php
function encrypt_password($pass) {
    $salt = "!#*[;";
    return hash("sha512", $pass . $salt);
}

// how to use it 
// if user gives password: admin123
encrypt_password('admin123')
// will return this string, I am breaking it in two lines do to line wrapping issue
// c0ce47bd96234bdfc5037be76eef3c32676cabdcb1a9d98d6ee45633502c72e
// 695ca7b6a35c1bc88359087c71eac26add64b09a5d8d7da5f2c36d5859ad2fa2c

?>

Final database table schema and a sample user record.
CREATE TABLE  `users` (
    `id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
    `username` VARCHAR( 255 ) NOT NULL UNIQUE ,
    `password` VARCHAR( 255 ) NOT NULL ,
    `status` ENUM(  'Y',  'N' ) NOT NULL DEFAULT  'N'
);

-- password is admin123 generated via sha512 and a salt is also append to it 
-- I am breaking the password string due to line wrap issue
INSERT INTO `users` (`id`, `username`, `password`, `status`) VALUES (NULL, 'admin', CONCAT('c0ce47bd96234bdfc5037be76eef3c32676cabdcb1a9d98d6ee45633502c72e695ca', '7b6a35c1bc88359087c71eac26add64b09a5d8d7da5f2c36d5859ad2fa2c') , 'Y');

Create a common file that will have a common session handling, database connection and error messages codes. Let’s name it configure.php. Enter your database credentials. You can also give a session name.
<?php
// display all error except deprecated and notice  
error_reporting( E_ALL & ~E_DEPRECATED & ~E_NOTICE );
session_name("sample-login-script");
session_start();

// turn on output buffering 
ob_start();

define('DB_DRIVER', 'mysql');
define("DB_HOST", "localhost");
define("DB_USER", "root");
define("DB_PASSWORD", "");
define("DB_DATABASE", "sampletest");

require_once("functions.php");

// basic options for PDO 
$dboptions = array(
    PDO::ATTR_PERSISTENT => FALSE,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
);

//connect with the server
//connect with the server
try {
    $DB = new PDO(DB_DRIVER . ':host=' . DB_HOST . ';dbname=' . DB_DATABASE, DB_USER, DB_PASSWORD, $dboptions);
} catch (Exception $ex) {
    echo errorMessage($ex->getMessage());
    die;
}

?>

Create a file functions.php that has error message and redirect functions.
<?php

function errorMessage($str) {
    return '<div style="width:50%; margin:0 auto; border:2px solid #F00;padding:2px; color:#000; margin-top:10px; text-align:center;">' . $str . '</div>';
}

function successMessage($str) {
    return '<div style="width:50%; margin:0 auto; border:2px solid #06C;padding:2px; color:#000; margin-top:10px; text-align:center;">' . $str . '</div>';
}

function redirect($url) {
    echo '<script type="text/javascript">window.location = "' . $url . '";</script>';
}

?>

Now create a login form which will be the landing page for any unverified user. Create a file name index.php.
<?php
require("configure.php");
if (isset($_SESSION["username"]) || $_SESSION["username"] != "" ){
	//if user already logged in
	redirect("home.php");
}
?>
<form method="post" action="" name="db">
        <input type="hidden" value="login" name="mode" />
        <div class="loginbox">
            <div class="col_left">Username: </div><div class="col_right"><input type="text" name="uname" value="<?php echo $userame; ?>" autocomplete="off" class="inputbox"  /></div>
            <div class="height10"></div>
            <div class="col_left">Password: </div><div class="col_right"><input type="password" name="upass" value="" class="inputbox"   /></div>
            <div class="height10"></div>
            <div class="col_left">&nbsp;</div><div class="col_right"><label for="remember_me"><input type="checkbox" value="1" name="remember_me"> Remember me </label> </div>
            <div class="height10"></div>
            <div class="col_left">&nbsp;</div><div class="col_right"><input type="submit" name="sub" value="" class="submitButton" /> </div>
            <div class="height10"></div>
        </div>

</form>

After the user submits form you need to validate and process the data accordingly. Let’s break down the code in 3 steps:
  1. Data validation
  2. Check for the username and password from database
  3. Check for the user status

1. Data Validation.

<?php
// add addslashes() function to prevent from sql injections
$uname = trim($_POST["uname"]);
$pass = trim($_POST["upass"]);
$rem = trim($_POST["remember_me"]);

if ($uname == "" || $pass == "" ) {
   echo errorMessage("Enter credentials properly!");
} else {
   // process data here
}
?>

Since we are use PDO classes, so any sql injections hack like this wont work thus securing sql injection.
In the password field instead of giving your password. try
' AND 1=1'

2. Check for username and password

<?php
// check if username exist 
$sql = "SELECT * FROM users where username = :uname";
try {
	$stmt = $DB->prepare($sql);
	$stmt->bindValue(":uname", $uname);
	$stmt->execute();
	$usernameRS = $stmt->fetchAll();
} catch (Exception $ex) {
	echo errorMessage($ex->getMessage());
}
if (count($usernameRS) > 0 ) {
	// user exist
	$sql = "SELECT * FROM users where username = :uname AND password = :pwd";
	try {
	  $stmt = $DB->prepare($sql);
	  $stmt->bindValue(":uname", $uname);
	  $stmt->bindValue(":pwd", encrypt_password($pass));

	  $stmt->execute();
	  $userRS = $stmt->fetchAll();
	} catch (Exception $ex) {
	  echo errorMessage($ex->getMessage());
	}

	if (count($userRS) > 0 ) {
	  // valid login details 
	} else {
	  // invalid login details
	}
}
?>

3. Check the status of the user.

<?php
if ($userRS[0]["status"] == 'Y') {

	$_SESSION["username"] = $userRS[0]["username"];

	if ($rem == 1) {
		// if user select to remember 
		setcookie("userame", $uname, time() + 7200);
	} else {
		setcookie("userame", $uname, time() - 7200);
	}

	redirect("home.php");
} else {
	// user exist but the status is inactive
	$errMSG = errorMessage("Sorry!!! But the account is temporary suspended.");
}
?>

Create a page home.php that will be the home page for valid user after login.
<?php
require("configure.php");
if (!isset($_SESSION["username"]) || $_SESSION["username"] == "" ){
	redirect("index.php");
}
?>
<div style="text-align:center;">
   <?php echo successMessage ("Successfully logged in by verified user."); ?>
   <br><br>
   <a href="logout.php"><img src="logout.png" alt="logout" width="103" height="39" border="0" /></a>
</div>

Now the last part the logout page. Make a file name logout.php
<?php
require("configure.php");
session_destroy();
redirect("index.php");
?>

 

View Demo

Share to download the Source Codes for FREE!
We're glad to give free downloads, but we need your love to carry on making that.
Please support us by sharing the page.

This is the most basic version of the secure login, You can use other techniques like captcha, 2 step verification. If you have any other ideas share with us.

Get the latest updates directly in your inbox for FREE: Subscribe here

Share your feedback / let me know your doubts regarding this tutorial in the comment box given below.

Share:
Hasan

Shahrukh Khan (Hasan)

A software engineer who's a die-hard coder, blogger, dreamer and mentor with years of expertise in web development. Know more...

Related Posts

Khurshid Md Anwar on

Very nice and knowledgeable information. I have admired your article. Keep giving us good article.

Reply
thesoftwareguy on

Thank you..

Reply
Rajiv Shaw on

Excellent One. The demo was helpful.

Reply
Nitish Kasar on

Again a good script , keep it up bro

Reply
khan on

when i open this :

http://localhost/login-script/index.php

it gave me this error :

Notice: Undefined index: username in C:xampphtdocslogin-scriptindex.php on line 7

however every thing works fine

and thanks

Reply
Shahrukh Khan on

use this at the top of your script

error_reporting(E_ALL^E_NOTICE);

Reply
lirk on

thanks a lot for sharing this code , was easy to understand .

by the way , is there a way to have specific home page for each user after he login ? or specific home page for each type of user ?

for example : if his [type] is admin , then when he login he will be redirected to admin home page

if his [type] is user , then he will redirected to user home page

Again a good code , keep it up bro

Reply
Shahrukh Khan on

That is a multi admin concept. yes it can be done. If i find time I will code that project.

Reply
Nasik on

You can use a encryption algorithm to avoid the ‘sql injuction ‘ , like ‘MD5()’ ..
be cause of that you have to encrypt the password before you pass the perrameter to the check password function .
any way gud job…
keep going

Reply
Shahrukh Khan on

Thanks for your suggestion. Yes I have updated the code, I had earlier used MD5(), but now I am using sha512() hash along with a extra characters ( Salt ) to make the password hash more secure. check the custom encrypt_password() I have used in this tutorial.

Reply
Javi on

Good article!

A good addition to this example would be to add a token with an expiration time to prevent, i.e., password exploit requests.
On the other hand, another approach to generate the password hash could be using the bcrypt password hash algorithm (If you are using a PHP version >= 5.5 you could use password_hash function -> http://php.net/manual/en/function.password-hash.php)

Reply
Dávur on

Great article. I would however suggest that you get much cleaner code if you move all styling to a CSS file that you reference through IDs and class references, since that is what you would always want to do that in real world projects 😉

Keep up the good work

Reply
Shahrukh Khan on

Thanks Dávur, Yes I do practice, The styling are in the css file only in the final downloadable file.

Reply
Marco on

Hello, how can I show a content, such as a link only to those who are logged in?

Reply
Shahrukh Khan on

Check the session id of the logged in user to show them links.

Reply
Bram on

Thanks a lot for sharing this. Where i can download this sample?

Reply
Bram on

i found it 🙂

Reply
Ray.W on

Hi, Mr. Khan,
I haven’t tried out any of your codes yet, I just want to appreciate your work, especially on the fact that you reply personally on most of the questions that were asked also in most of your other posts, that is a really good practice for an admin for an educational type of page/website. Keep up the good work.
Thanks,
Ray.W

Reply
Shahrukh Khan on

Thanks a lot Ray. Comments like these give me a boost and inspire me to work with more love and passion.

Reply
Emmanuel on

Thank you for this tutorial.

It helps a great deal but please how do I use that hash generator? I need to use another password, please help

Regards

Reply
Shahrukh Khan on

you can use many hashing function like md5, sha1 etc. you can also you password_hash function. check the official documentation for more information

Reply
Himanshu Ranjan on

sir, how can i to generate a hash for my password.

Reply
Shahrukh Khan on

you can use many hashing function like md5, sha1 etc. you can also you password_hash function. check the official documentation for more information

Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.