A simple Secure Login Class using PHP and MySQL
Login System is always required for any web application that is dynamic. So, this is what actually happened to me. Every website I created, require some form of login system. So, I usually integrate a login system. The problem is that when I update some security features, I've to re-code for all those website. This unique problem, leads me to the creation of this tutorial inspired by the Hashing Security blog.
The idea here is to separate the login system from the rest of the application. The best way to implement this is to use a Login Class and simply integrate the class to any application you design. In this tutorial, I would like to make the login system as secure as possible, hence I would like to ensure a strong encryption of passwords. Now instead of designing my own encryption technique, I'll use a strong and reliable technique described by Crack Station - a Hashing Security blog. Hence before you start download this PasswordHash.php file from GitHub.
This Tutorial will be in three parts:
- Designing the Database
- Creating the Login Class
- Implementing the Class.
Designing the Database: Let's create a simple database containing the following fields:
In the above structure, we have a userid, username, password, useremail and userlevel. You can create the database table using any tools you like. My choice is phpMyAdmin, or you can simply copy this SQL statement and use it directly.
The userid is also set as the primary key. You can use the utf8 CHARSET too if you want. Let us take some time to understand this basic SQL table. The username and user email are two different field. Hence, a user will need a username to login. You can also set that username should be UNIQUE or combine both username and useremail as UNIQUE fields. The userlevel field is used in case where your website users are of different levels. Example:
- Administrator | Level - 0
- Editor | Level - 1
- Subscriber | Level - 2
Finally, create a configuration file (let's name it db-config.php). In this file, database login information is defined as follows:
Save this file in your application folder - preferably set an include folder and save there. So, with this, we have come to the conclusion of the first part of this tutorial.
Creating the Login Class: The second part of this tutorial is to create the login class to use with our application. Now, I would remind you that I'll be using an encryption technique which is strong and secure as described by Crack Station - a Hashing Security blog. Hence before you start make sure you've download this PasswordHash.php file from GitHub save the file in the same include folder that you've saved the db-config.php file.
Now, create a file and let's name it loginClass.php. Here, we will place all our login system. The empty file will look something like this:
In the above file, we have started a session, then set the error reporting and created an empty class loginClass. Before we go ahead, let us simplify the process of accessing our database. Here, we'll implement PDO prepared statement. So, we'll extends the PDO class and make things simpler. We'll modify our loginClass.php file by adding another class just before our loginClass as follows:
The above extended class will allow for simpler coding in our loginClass. Next we will see how to create the functions which will help in building our application.
So, you've seen about how to setup a database. Next, in the loginClass we'll build the different methods that will be used in any application as a login system. Firstly, we'll set some private variables. In Objected Oriented Programming, private variables are accessible only by the methods of the class and not from outside. Some, important variables can be set as private here:
Here, we've set the database information and the structure of the tables and some messages variables. The next part is to create public functions to make the class functioning. The functions (methods) that we'll implement are the following:
These are four important functions required for a login system, we can extend the system further, but as of now we'll first take a look at these four functions. So, let's break down these four functions one by one.
The function isUserLoggedIn() check if a user has already logged in. This is possible through session variables that we will set every time a user login. The login() function will allow for logging in a user, set important session variables. The registerUser() is understandable function to register new users into the system. The last function is simply used to logout any active user and destroy/unset session variables. So, here are the codes for the different functions. Firstly, the login() function:
Here, basically the function check first if username exist, if the username exist, check for password match, if input password match the saved password, then login the user. After a user login, session variables are registered. You can include as many as your application require. Here, I've kept five session variables that store userid, username, userlevel, useremail and a loggedin state. If the password didn't match, for security reasons send a generic message as Invalid Credentials rather than saying Invalid Password. Also, if the user don't exist, again send a generic message Invalid Credentials rather than User Doesn't exist. This, will prevent hackers from guessing the right username that exist.
Next, we'll look at the isUserLoggedIn(). This function is quite simple - all it does is check if the SESSION['loggedin'] is set or not. If it is set and value is true, then return positive. So, an application just check this value and if it exist, display the secure part of the application - we'll talk about this part later in our implementation of this class.
The next part is the function to register new users. In this function, the username, useremail are first check if they are already exist in the database. If either username or useremail is already registered, then the registration process is stopped. If everything is in order, the password is hashed first using the PasswordHash class. The hashed password, username and email is then stored into the database. The function will look something like this.
Finally, the last function is to logout an active user. Here, we will deregister the session using unset. If your application doesn't need any use other session data, then you can destroy the session or to be safe unset is the best practice. Now our logout function will look like this:
In order to secure our application, we'll implement a data sanitization. For example an email must be a valid email address. We will also limit the characters that can work with a username - say we'll allow only alphanumeric (aA to zZ and 0-9) with the underscore character "_". Now to do that, we'll create two functions that can handle this part. PHP from version 5 and above has some filters to validate and also to sanitize. Validation is required to check if the email/username is within our allowed characters and format. While sanitization is to prevent SQL injection. The two functions can be written as follows:
Our completed loginClass.php file now looks like the following (You can double click on the code area to copy the whole class and function):
The Final Part of this tutorial is how to implement the loginClass that we've created earlier. Before we go ahead, make sure the following files are present in your folder. My folder arrangement is as follows:
My application resides inside localhost folder. Then, the db-config.php, loginClass.php and PasswordHashClass.php are saved inside the include folder. Now, in the main folder - the localhost folder, create four new files - index.php, register.php, logout.php and style.min.css. index.php will act as a place to login users. The register.php file will allow for registration of new users, while the logout.php will be used to logout and the style.min.css will be used to place our CSS. So, let's start with the index.php file.
||||- - includes|
|||||||- - db-config.php|
|||||||- - loginClass.php|
|||||||- - PasswordHashClass.php|
||||- - index.php|
||||- - logout.php|
||||- - register.php|
||||- - style.min.css|
Here, the request variables is first checked. If they exist, it means the user has already post the data. Hence validate and login the user. The next part the user is then checked if already logged in or not. If not login then show login form. Now, let us see the register.php file. This file will look like this:
Here, also request variables is check, if user already post the data. Then validation takes place and finally insert the data. The logout.php file is rather simple and will just call the logout() method:
Finally a little touch of styling for the form to display. I've modified the CSS taken from Sanwebe.com for this tutorial. The modified CSS looks like this:
In conclusion, we've successfully created a simple login script. Now what is next thing to do from here. Security is the main important part of any login system, this login system allows for data sanitization. Further extension to this class could be to include a reset-password function, send email on registration. I'm concluding this part here but in the near future, I will bring about some more changes to this loginClass and add those additional features. Till then stay tune.