User login system using PHP

User login system using PHP

Hello there, today we are going to create a secure user login system using PHP. For security reasons, passwords are not stored in the database in clear text format. They are hashed using some mechanism and stored. One of the mechanism used is hashing using salt. A salt is simply added to make a common password uncommon.

This post is meant to teach you the basics of PHP cyrpt() function and store passwords using salt. If you do not know what they are and want to learn. Here is a great answer on stackexchange.

At the end of this tutorial you will have a login system that uses database, session and encryption to build a login system that can be used in your project or anywhere that you wish to.

Before we begin the following video is a demo of what we are going to build:

Prerequisites:

Some basic HTML, PHP, mySQL and localhost testing on XAMPP or WAMP server.

HTML and some basic Bootstrap will be used on the front-end. Do not worry if you know nothing about Bootstrap, since you can pretty much follow along without it. Bootstrap is used here only to make the system look a little prettier.

Some basic knowledge of PHP will help you follow along easier but I will try my best to make it clear for everyone.

Now PHP is a server side scripting language. That means it works on the server side and not on the local machine. So to run php applications on your computer you will need either XAMPP or WAMP .

Okay now lets get on with it.

The first step is to download Bootstrap :

This is optional but I recommend you do it, since you will get a chance to learn some of it as well. Learning Bootstrap will help you create responsive mobile-friendly websites.

Second, install xampp or wamp:

You will need some sort of “server”  to run php scripts that we are going to create. These programs will help you use your local machine as a local server. The tutorial will be Xampp specific but I hear it is more or less the same on Wampp.

Third install sublime text:

It is a free (well almost) text editor that we will be using to code. Or you can use any text editor or IDE of your choice.

Fourth step:

Create a folder inside C:/xampp/htdocs/ or wherever you chose to install Xampp, which will be the working folder or the projects folder. Example: C:/xampp/htdocs/LoginSystem

Then extract the bootstrap zip folder (the one that we downloaded on the first step) to our project folder.

By now your project folder should have the following folders in it: css , font and js folders in it from the bootstrap extraction.

Now the coding part, well the most of it:

Open sublime text and click File>Open Folder and select our project folder and create 6 new files. File>New File and name them, save as .php files. I have named them:

  1. index.php
  2. login.php
  3. logout.php
  4. newuser.php
  5. register.php
  6. user_dashboard.php

The names are self descriptive as you can see. They are all for respective  functionalities.

Now lets work on index.php

The index.php is our homepage or in this case, the login page. The code for index.php is:

<html>
<head>
<title>Password Salting</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstap-theme.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<div class="container">
<div class='row'>
<div class='col-sm-12'>
<form action="login.php" method="POST" role='form'>
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" placeholder="Enter your username" >
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" placeholder="Password">
</div>
<input type="submit" class="btn btn-default" value="Sign In">.
</form>
<br><br>
<text class="text-muted">Not registered? Sign up easily!</textarea>
<br>
<a href="newuser.php" class="btn btn-default" role="button">Sign Up</a>
</div>
</div>
</div>
</body>
</html>
view rawindex.php hosted with ❤ by GitHub

Basically what this does is, it displays a form with username and password fields and sign in button. Or if the user is not signed up, a sign up button can be clicked to sign up.

An important thing to notice here is to put appropriate php files for form action attribute. The file put there is opened once the form is filled and submit button is clicked. The other important thing here is form method attribute. We have used POST method here. The POST method is used to retain the values provided in the form input ie. username and password. You can read more about POST method here.

So on clicking the sign in button a POST method is invoked and  login.php is opened up. While on clicking the sign up button newuser.php is opened up. That’s it.

In case you don’t know, you can view index page by typing localhost/your_project_name in your browser. Also your xampp server should be running:

Xampp running " data-medium-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture.png?fit=300%2C193&ssl=1" data-large-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture.png?fit=674%2C434&ssl=1" loading="lazy" class="size-full wp-image-686 td-animation-stack-type1-2" src="https://i1.wp.com/ktmbytes.com/wp-content/uploads/2018/10/Capture.png?resize=674%2C434&ssl=1" alt="Xampp running" width="674" height="434" srcset="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture.png?w=674&ssl=1 674w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture.png?resize=300%2C193&ssl=1 300w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture.png?resize=210%2C136&ssl=1 210w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture.png?resize=600%2C386&ssl=1 600w" sizes="(max-width: 674px) 100vw, 674px" data-recalc-dims="1" data-pagespeed-url-hash="128955397" onload="pagespeed.CriticalImages.checkImageForCriticality(this);" style="box-sizing: border-box; border: 0px; max-width: 100%; height: auto; transition: transform 0.5s ease 0s, opacity 0.3s cubic-bezier(0.39, 0.76, 0.51, 0.56) 0s; opacity: 0; transform: scale(0.95); margin-bottom: 0px; width: 674px; display: block;" />
Xampp running

The index page output should look like this: (To open this type localhost/your_project_name  in your browser)

 

secure login blog index page

" data-medium-file="https://i2.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture1.png?fit=300%2C83&ssl=1" data-large-file="https://i2.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture1.png?fit=696%2C192&ssl=1" loading="lazy" class="size-large wp-image-689 td-animation-stack-type1-2" src="https://i2.wp.com/ktmbytes.com/wp-content/uploads/2018/10/Capture1-1024x282.png?resize=696%2C192&ssl=1" alt="secure login blog index page" width="696" height="192" srcset="https://i2.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture1.png?resize=1024%2C282&ssl=1 1024w, https://i2.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture1.png?resize=300%2C83&ssl=1 300w, https://i2.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture1.png?resize=768%2C211&ssl=1 768w, https://i2.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture1.png?resize=600%2C165&ssl=1 600w, https://i2.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture1.png?w=1366&ssl=1 1366w" sizes="(max-width: 696px) 100vw, 696px" data-recalc-dims="1" data-pagespeed-url-hash="2988280798" onload="pagespeed.CriticalImages.checkImageForCriticality(this);" style="box-sizing: border-box; border: 0px; max-width: 100%; height: auto; transition: transform 0.5s ease 0s, opacity 0.3s cubic-bezier(0.39, 0.76, 0.51, 0.56) 0s; opacity: 0; transform: scale(0.95); margin-bottom: 21px; display: block;" />

Now we would need a database to insert our user’s details on. To create a database, open your browser and type localhost/phpmyadmin:

Localhost PHPMyadmin " data-medium-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/Capture.png?fit=300%2C92&ssl=1" data-large-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/Capture.png?fit=696%2C214&ssl=1" loading="lazy" class="size-full wp-image-708 td-animation-stack-type1-2" src="https://i0.wp.com/ktmbytes.com/wp-content/uploads/2018/11/Capture.png?resize=696%2C214&ssl=1" alt="Localhost PHPMyadmin" width="696" height="214" srcset="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/Capture.png?w=830&ssl=1 830w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/Capture.png?resize=300%2C92&ssl=1 300w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/Capture.png?resize=768%2C236&ssl=1 768w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/Capture.png?resize=600%2C184&ssl=1 600w" sizes="(max-width: 696px) 100vw, 696px" data-recalc-dims="1" data-pagespeed-url-hash="678743303" onload="pagespeed.CriticalImages.checkImageForCriticality(this);" style="box-sizing: border-box; border: 0px; max-width: 100%; height: auto; transition: transform 0.5s ease 0s, opacity 0.3s cubic-bezier(0.39, 0.76, 0.51, 0.56) 0s; opacity: 0; transform: scale(0.95); margin-bottom: 0px; width: 696px; display: block;" />
Localhost PHPMyadmin

 

Create new database and name it, I have named mine practise. Then create a table named users with the following columns in it:

User table columns " data-medium-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture2.png?fit=300%2C108&ssl=1" data-large-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture2.png?fit=696%2C251&ssl=1" loading="lazy" class="size-large wp-image-690 td-animation-stack-type1-2" src="https://i0.wp.com/ktmbytes.com/wp-content/uploads/2018/10/Capture2-1024x369.png?resize=696%2C251&ssl=1" alt="User table columns" width="696" height="251" srcset="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture2.png?resize=1024%2C369&ssl=1 1024w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture2.png?resize=300%2C108&ssl=1 300w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture2.png?resize=768%2C277&ssl=1 768w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture2.png?resize=600%2C217&ssl=1 600w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/10/Capture2.png?w=1103&ssl=1 1103w" sizes="(max-width: 696px) 100vw, 696px" data-recalc-dims="1" data-pagespeed-url-hash="2374658103" onload="pagespeed.CriticalImages.checkImageForCriticality(this);" style="box-sizing: border-box; border: 0px; max-width: 100%; height: auto; transition: transform 0.5s ease 0s, opacity 0.3s cubic-bezier(0.39, 0.76, 0.51, 0.56) 0s; opacity: 0; transform: scale(0.95); margin-bottom: 0px; width: 696px; display: block;" />
User table columns

I am going fast on this because phpmyadmin is fairly easy to use because of its GUI, but you can also use sql query to create the table as:

CREATE TABLE `users` (
  `id` int(3) UNSIGNED NOT NULL,
  `fname` text NOT NULL,
  `lname` text NOT NULL,
  `email` varchar(23) NOT NULL,
  `username` varchar(23) NOT NULL,
  `password` varchar(23) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


--
ALTER TABLE `users`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `username` (`username`),
  ADD KEY `username_2` (`username`);

And the database part is done.

Now that we have a database, let us create a new user using the sign up functionality

The code for the signup page (newuser.php) is :

<html>
<head>
<title>Sign up form</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstap-theme.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-12">
<form action="register.php" method="POST" role='form'>
<div class="form-group">
<label for="fname">First Name</label>
<input type="text" class="form-control" name="fname" placeholder="Enter your first name" >
</div>
<div class="form-group">
<label for="lname">Last Name</label>
<input type="text" class="form-control" name="lname" placeholder="Enter your last name" >
</div>
<div class="form-group">
<label for="email">Email address</label>
<input type="email" class="form-control" name="email" aria-describedby="emailHelp" placeholder="Enter email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="fname">Username</label>
<input type="text" class="form-control" name="username" placeholder="Select a unique username" >
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" placeholder="Password">
<br>
<input type="submit" class="btn btn-default" value="Register">.
</div>
</form>
</div>
</div>
</div>
</body>
</html>
view rawnewuser.php hosted with ❤ by GitHub

So the newuser.php is fairly simple with a form containing fields: firstname, lastname, username , email and password; the same fields that our database has. The form has register.php in form action   tag, so when the form is filled and Register button is clicked, register.php is run which looks like:

view rawregister.php hosted with ❤ by GitHub

Now this snippet might look short but there are a lot of things that need explanation here. You can also see that I have used a particular function named ` crypt whereby I hace passed the password from the POST request from our newuser.php ‘s form and $salt which is used to hash the password from the user and store to our database. $hased_password  variable stores the hashed password after crypt() function does its job. If you want to read more on crypt()   function, you can do so by going here.

 

Now session_start() means we are starting a session so that we can get the values entered by the user in newuser.php. Remember we are now in register.php. So in order to be able to get those user entered values we need session_start() and POST   values. Line 11-15 are just declaring variables and taking values from the POST method.

By this time the user entered password is hashed successfully but the data is not put in the database. That is what line 22 to 32 does. The value for id is left empty because, id is set to AI (Auto Increment) in  our database.

The process till now is sign up on homepage>newuser.php>register button>register.php> INSERT into users.

So we will be able to create users for the database. The password field on the database will look like as shown below:

salted password example " data-medium-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/hashed_password.png?fit=300%2C133&ssl=1" data-large-file="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/hashed_password.png?fit=696%2C309&ssl=1" loading="lazy" class="size-full wp-image-706 td-animation-stack-type1-2" src="https://i2.wp.com/ktmbytes.com/wp-content/uploads/2018/11/hashed_password.png?resize=696%2C309&ssl=1" alt="salted password example" width="696" height="309" srcset="https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/hashed_password.png?w=768&ssl=1 768w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/hashed_password.png?resize=300%2C133&ssl=1 300w, https://i1.wp.com/old.ktmbytes.com/wp-content/uploads/2018/11/hashed_password.png?resize=600%2C266&ssl=1 600w" sizes="(max-width: 696px) 100vw, 696px" data-recalc-dims="1" data-pagespeed-url-hash="2438255905" onload="pagespeed.CriticalImages.checkImageForCriticality(this);" style="box-sizing: border-box; border: 0px; max-width: 100%; height: auto; transition: transform 0.5s ease 0s, opacity 0.3s cubic-bezier(0.39, 0.76, 0.51, 0.56) 0s; opacity: 0; transform: scale(0.95); margin-bottom: 0px; width: 696px; display: block;" />
salted password example

 

The password is stored in the database in hashed form.

The sign in functionality:

What happens when we enter username and password on the index page and click sign in? From index.php , we can see that clicking sign in after entering the username and password will use POST method and open login.php.

In login.php we will have to check if the username and password provided is in our database.

The code for login.php is:

view rawlogin.php hosted with ❤ by GitHub

The connection to the database is made using lines 3 to 4. If a link could not be established to the databse it also throws out debug information on the screen becasue of lines 4 ot 9. Now crypt() is a one way string hashing, so there is no comparing the password provided during sign in with the password in the database by decrypting it. In other words there is no decrypt() function. So what I have done here is encrypt the password provided during sign in and compare with the value in the database. Finally if the username and password are valid, user_dashboard.php is opened up.

>
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstap-theme.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-theme.min.css">
</head>
<body>
<script type="text/javascript">alert('')</script>
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="jumbotron">
<h1> Unauthorized </h1>
<h2> You are not logged in </h2>
<a href="index.php" class="btn btn-default" role="button">Log in</a>
<h1>Hello,!</h1>
<a href="logout.php" class="btn btn-default" role="button">Log out</a>
<h2 style="letter-spacing: 4px;">This is letters spaced at 4px</h2>
</div>
</div>
</div>
</div>
</body>
</html>

The logout functionality is implemented with logout.php. The code to logout.php is:

view rawlogout.php hosted with ❤ by GitHub

The logout functionality is basically opening the databse connection and selcting our table. On successfull connection we start a session adn check if the sesion variable for username is set or not. If the session variable for username is set, that means the user is logged in and the user is logged out by clearing the session. If the session variable is not set or the session variable is empty, there is no one logged in and the system echoes out “Could not logout”

And there you have it your secure user login system using php. I know this tutorial is not super easy to understand and I have been lazy to make many concepts clearer but you can find the full github project repository here: Github repo and make it work on your local machine and do some self research. You yourself are the best teacher for you. If you do not know how to use git and github, consider reading our post on getting started with git and github.

In addition to that I made this system quite a while ago, infact when PHP 7 was not here with all its improved functions mysqli_something. “i” for improved. So I had to make some adjustments here and there to make it work. The code is not clean at all, my apologies, but it does work. If you want to have a look at my previous code which I wrote for PHP 5, I think you can follow this blog post and in my github repo, you can go view the project on the commit on  Jun 7, 2017.

Also do comment if you have any questions or if you want me to cover a particular topic in this post in detail.