Login form

In this example we will see how to make a login mechanism in PHP. The login systems is one of the most liked targets of attackers, so we have to be extremely careful with every aspect of the login.

For this tutorial, we will use:

  • Ubuntu (14.04) as Operating System.
  • Apache HTTP server (2.4.7).
  • PHP (5.5.9).
  • SQLite3, a lightweight and process-less DBMS. Credentials are almost always saved in databases, so we have chosen the lightest option for developing purposes. This not should be an option in production environments.

1. Preparing the environment

1.1. Installation

Below, commands to install Apache, PHP and SQLite are shown:

sudo apt-get update sudo apt-get install apache2 php5 libapache2-mod-php5 php5-sqlite sudo service apache2 restart

1.2. PHP configuration

We have to configure PHP to add the SQLite driver. Open /etc/php5/apache2/php.ini, and add the following directive, if it not exists:


Don’t forget to restart Apache after doing any change.

Note: check the write permissions of your working directory, since the database will be placed in that directory.

2. How should passwords be stored?

After developing any login system, we first need to decide how the passwords are going to be stored. Let’s see which are the possible ways to store password, from worse option, to best:

2.1. Worse: plain text

Even if can be an obviousness, is something that must be said (mostly, because it’s still being done): please, don’t store passwords in plain text. At the same time a password is stored as plain text, it’s compromised. Anyone having access to the password storage (commonly, a database), will know the password, when is something that is thought to be known only by its owner. And if the system is compromised by the attacker, it would have all the passwords readable.

2.2. Not bad: password hashing

To avoid this, password hashing was designed. This consists on calculating the hash of the password, to store that hash. Hash functions are one-way functions, that is, if hf(password) = hash, where hf is the hash function, is computationally unfeasible to deduce password from hash. So, for a login, the stored hash has to be compared with the hash of the password provided but the user.

Password hashing is a much better password storing system that plain text, but keeps being vulnerable. Precomputed tables of hash values could be used (many of them are available already on Internet) to force the login, or to get the original password from its hash, also called digest. One of the features of hash functions is that they are extremely fast, and this, for login, is a disadvantage, since an attacker has more chances to attempt logins in less time.

2.3. Better: password hashing + salting

This solves, partially, the problem described in paragraph above. Salting consists on adding a random string of bytes (called salt) to the password before its hashing. So, same passwords, would have different hashes. To perform the login, the hash of the password provided by the user plus the stored salt for that user has to be calculated, and then compare with the stored one.

If an attacker uses a precomputed table of hash values, it still could attempt a brute-force attack, but it won’t be possible that easy to revert the hash to get the plain password, because the random salt has been part of the hash calculation.

In this case, to calculate the hash, we would do the following: hf(password + salt) = hash.

Note: when calculating salts, strong random functions based on entropy should be used, not that weak and predictable functions like rand()


2.4. Even better: Key Derivation Functions

As we said above, password hashing plus salting helps to keep the passwords secret against precomputed table-like attacks. But an attacker could gain access to a system with a brute-force attack, without needing to know the password.

To avoid this, Key Derivation Functions (KDF) where designed. This functions are design to be computationally intense, so, needs much time to derive the key. Here, computationally intense, means a second, maybe something more. Actually, the concept is the same that in hashing + salting, but here another variable is used: the computational cost, which defines the intensity we mentioned above.

So, the operation would be: kdf(password, salt, cost) = dk, where dk is the derived key generated.

Let’s see a time comparison between a common hash function (SHA1, which is deprecated, but it’s still widely used), and a KDF (bcrypt):


<?php  $password = 'An insecure password';  $starttime = microtime(true); sha1($password); $sha1Time = microtime(true) - $starttime;  $bcryptOptions = array('cost' => 14); $starttime = microtime(true); password_hash($password, PASSWORD_BCRYPT, $bcryptOptions); $bcryptTime = microtime(true) - $starttime;  echo "sha1 took: $sha1Time s <br>"; echo "bcrypt took: $bcryptTime s <br>";

The output will be something like this (depending on the hardware):

sha1 took: 1.5020370483398E-5 s  bcrypt took: 1.2421669960022 s

As you can see, we reduce significantly the attempts an attacker could perform, passing from 1.5*10-5 seconds, to 1,2 seconds. And, for a user, waiting a second for a login is almost imperceptible.

Is it possible to adjust the intensity the algorithm takes, as in line 9, to find the value that fits better with our hardware.

The derived password (the return value of password_hash() function) will be similar to the following string:


Which follows the following format:

$<algorithm_id>$<cost>$<salt (22 chars)><hash (31 chars)>

So, in that example, would be:

  • Algorithm id: 2y (bcrypt).
  • Cost: 14
  • Salt: WH1yQiP1naJD8b8lWOK1bO
  • Hash, or derived key: xGQUjgCpFwuzSKohGL/ZV1NaYYr5Cge

Taking this into account, for authenticating the user, we would have to extract the cost and the salt to reproduce the operation, to then compare the hashes. We will see this in the login implementation.

Note: in the password_hash() function, in the $options array, we can also specify a salt. If any salt is specified, the function will generate one. For creating salts, the recommended way is using mcrypt_create_iv()


3. Creating users

Let’s do a simple script that allows to create user, to later test that our login system works correctly.


<?php  require_once('db.php');  function checkGETParametersOrDie($parameters) {     foreach ($parameters as $parameter) {         isset($_GET[$parameter]) || die("'$parameter' parameter must be set by GET method.");     } }  checkGETParametersOrDie(['username', 'password']);  $username = $_GET['username']; $password = $_GET['password'];  $db = new DB(); $db->createUser($username, $password);  echo "User '$username' has been created successfully.";

To create the user in the database, we developed a class named DB. We will see it below. Now, enter the URL to the script location:

With the username and password you prefer.

4. Login

4.1. Form

A simple login form that asks for an username and password.


<!DOCTYPE html> <html> <head>     <meta charset="UTF-8">     <title>Login form</title> </head> <body>     <form action="lo.  

orm> </body> </html>

4.2. Form handling

To handle the form, we will create the following script:


<?php  require_once('db.php');  /**  * Checks if the given parameters are set. If one of the specified parameters is not set,  * die() is called.  *  * @param $parameters The parameters to check.  */ function checkPOSTParametersOrDie($parameters) {     foreach ($parameters as $parameter) {         isset($_POST[$parameter]) || die("'$parameter' parameter must be set by POST method.");     } }  // Flow starts here.  checkPOSTParametersOrDie(['username', 'password']);  $username = $_POST['username']; $password = $_POST['password'];  $db = new DB();  $authenticated = $db->authenticateUser($username, $password);  if ($authenticated) {     $response = "Hello $username, you have been successfully authenticated."; } else {     $response = 'Incorrect credentials or user does not exist.'; }  echo $response;

Actually, only retrieves the parameters sent by the form, and calls DB class function authenticateUser() method. Let’s see now that class.

4.3. Login against database

The interesting part. This class is the one that interacts with the database, to perform the login, and also to create the users:


<?php  /**  * Methods for database handling.  */ class DB extends SQLite3 {      const DATABASE_NAME = 'users.db';     const BCRYPT_COST = 14;      /**      * DB class constructor. Initialize method is called, which will create users table if it does      * not exist already.      */     function __construct() {         $this->open(self::DATABASE_NAME);         $this->initialize();     }      /**      * Creates the table if it does not exist already.      */     protected function initialize() {         $sql = 'CREATE TABLE IF NOT EXISTS user (                     username STRING UNIQUE NOT NULL,                     password STRING NOT NULL                 )';          $this->exec($sql);     }      /**      * Authenticates the given user with the given password. If the user does not exist, any action      * is performed. If it exists, its stored password is retrieved, and then password_verify      * built-in function will check that the supplied password matches the derived one.      *      * @param $username The username to authenticate.      * @param $password The password to authenticate the user.  

   * @return True if the password matches for the username, false if not.      */     public function authenticateUser($username, $password) {         if ($this->userExists($username)) {             $storedPassword = $this->getUsersPassword($username);             if (password_verify($password, $storedPassword)) {                 $authenticated = true;             } else {                 $authenticated = false;             }         } else {             $authenticated = false;         }         return $authenticated;     }     /**      * Checks if the given users exists in the database.      *      * @param $username The username to check if exists.      * @return True if the users exists, false if not.      */     protected function userExists($username) {         $sql = 'SELECT COUNT(*) AS count                 FROM   user                 WHERE  username = :username';         $statement = $this->prepare($sql);         $statement->bindValue(':username', $username);         $result = $statement->execute();         $row = $result->fetchArray();         $exists = ($row['count'] === 1) ? true : false;         $statement->close();         return $exists;     }     /**      * Gets given users password.      *      * @param $username The username to get the password of.      * @return The password of the given user.      */     protected function getUsersPassword($username) {         $sql = 'SELECT password                 FROM   user                 WHERE  username = :username';         $statement = $this->prepare($sql);         $statement->bindValue(':username', $username);         $result = $statement->execute();         $row = $result->fetchArray();         $password = $row['password'];         $statement->close();         return $password;     }     /**      * Creates a new user.

   *      * @param $username The username to create.      * @param $password The password of the user.      */     public function createUser($username, $password) {         $sql = 'INSERT INTO user                 VALUES (:username, :password)';         $options = array('cost' => self::BCRYPT_COST);         $derivedPassword = password_hash($password, PASSWORD_BCRYPT, $options);         $statement = $this->prepare($sql);         $statement->bindValue(':username', $username);         $statement->bindValue(':password', $derivedPassword);         $statement->execute();         $statement->close();     } }

Remember when we said in 2.4 section that, for comparing the provided password with the string generated by the KDF algorithm, we would have to extract the cost and the salt from that string? Well, the password_verify() function, in line 45, does this for us: repeats the operation for the provided $password, extracting the algorithm, the salt and the cost from the existing derived key $storedPassword

, and then compares it to the original password that is the “reference”.

Note that, when querying the database, we use something called $statement. These are called Prepared Statements. We can execute directly a string SQL with a SQLite method called exec(), but this would be vulnerable against SQL Injection, and an attacker could gain access to the system injecting SQL commands. The Prepared Statement does not allow this, because it binds the parameters using a different protocol, and don’t need to be escaped looking for characters like '.

If we try to fill the form with the credentials we created in section 3, we will receive the following message:

Hello <user>, you have been successfully authenticated.

Whereas, if we introduce incorrect credentials, we will see:

Incorrect credentials or user does not exist.

5. Summary

We have seen that there are different mechanisms to design a login system, analysing the weakness of each one, concluding that the KDFs are the most secure alternative currently, and how to implement it in PHP. We have also seen the need of the use of the Prepared Statements, not to allow hypothetical attackers to introduce malicious commands to gain access or to extract information.

6. Download the source code

This was an example of a login form in PHP.


Do you have a website? If your answer to this question is yes, then a classic must have is an attractive login form. Be it a social networking site or an online fashion store, an email site or an online magazine, the first thing that catches the eye of the customer is the login option. So, why not let your customer get the desired impression in the first contact. Download Html5 Signup and Registration Forms[Free] and get the look for your website that creates an everlasting first impression.

Helpful Articles:

  • HTML5 CSS3 UI Kits
  • HTML5 CSS3 jQuery DropDown Menus

HTML5 Tutorial – Creating Easy HTML Login Form using CSS!

How to Use Custom Login Form in Your Website

Creating a custom login form for your WordPress website is quite easy with the latest themes and templates. These free templates are fully customizable and editable. Now edit the login logo to make it more attractive. Replace the logo with your brand icon. It helps in the branding part and depicts a clear message the visitors. There are several plugins available that help in creating customized login form for your website. These plugins are easy to install and helps in providing the most innovative login pages that promises fully editable and responsive for your website. Using custom login form in your website just gets easier.

How to Design / Create Login Form in HTML

It is really important to business to have a nice and creative login form. This is the first point of contact for many customers and hence a lot of efforts should go in creating a perfect design login form. It is possible to code the entire webpage in HTML and there are also Free HTML5 & CSS3 Login Forms Downloads that are available on the web. These templates can be used with little modification and it saves a lot of time and efforts while designing any page. Some may prefer using the paid templates for the web designing and others may simply resort to creating it from scratch.


<!— Button to open the modal login form —>
<button onclick="document.getElementById(‘id01’).style.display=’block’">Login</button>

<!— The Modal —>
<div id="id01" class="modal">
  <span onclick="document.getElementById(‘id01’).style.display=’none’"
class="close" title="Close Modal">&times;</span>

  <!— Modal Content —>
  <form class="modal-content animate" action="/action_page.php">
    <div class="imgcontainer">
      <img src="img_avatar2.png" alt="Avatar" class="avatar">

    <div class="container">
      <label for="uname"><b>Username</b></label>
      <input type="text" placeholder="Enter Username" name="uname" required>

      <label for="psw"><b>Password</b></label>
      <input type="password" placeholder="Enter Password" name="psw" required>

      <button type="submit">Login</button>
        <input type="checkbox" checked="checked" name="remember"> Remember me

    <div class="container" style="background-color:#f1f1f1">
      <button type="button" onclick="document.getElementById(‘id01’).style.display=’none’" class="cancelbtn">Cancel</button>
      <span class="psw">Forgot <a href="#">password?</a></span>


You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.