Hi, we’re going to be using PHP and MySQL to build an authentication system. This will prevent guests from viewing certain pages on your given application without having an account. We’ll be using the Bootstrap Framework for presentation. Also, the stored passwords will be encrypted.
Registration System
Step 1: Creating the Database Table
Execute the following SQL query to create a “users” table in your MySQL database.
1 2 3 4 5 6 | CREATE TABLE users ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); |
Step 2: Creating the Config File
After creating the table, we need to create a PHP script in order to connect to the MySQL database server. Let’s create a file named “config.php” and put the following code inside it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?php /* Database credentials. Edit as required */ define('DB_SERVER', 'localhost'); define('DB_USERNAME', 'YOUR_USERNAME_HERE'); define('DB_PASSWORD', 'YOUR_PASSWORD_HERE'); define('DB_NAME', 'YOUR_DBNAME_HERE'); /* Attempt to connect to MySQL database */ $link = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD, DB_NAME); // Check connection if($link === false){ die("ERROR: Could not connect. " . mysqli_connect_error()); } ?> |
Step 3: Creating the Registration Form
Let’s create another PHP file called “register.php” and put the following code in it. This example code will create a web form that allows users to register themselves.
This script will also generate errors if a user tries to submit the form without entering certain values, or if the username entered by the user is already taken by another user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | <?php // Include config file require_once 'config.php'; // Define variables and initialize with empty values $username = $password = $confirm_password = ""; $username_err = $password_err = $confirm_password_err = ""; // Processing form data when form is submitted if($_SERVER["REQUEST_METHOD"] == "POST"){ // Validate username if(empty(trim($_POST["username"]))){ $username_err = "Please enter a username."; } else{ // Prepare a select statement $sql = "SELECT id FROM users WHERE username = ?"; if($stmt = mysqli_prepare($link, $sql)){ // Bind variables to the prepared statement as parameters mysqli_stmt_bind_param($stmt, "s", $param_username); // Set parameters $param_username = trim($_POST["username"]); // Attempt to execute the prepared statement if(mysqli_stmt_execute($stmt)){ /* store result */ mysqli_stmt_store_result($stmt); if(mysqli_stmt_num_rows($stmt) == 1){ $username_err = "This username is already taken."; } else{ $username = trim($_POST["username"]); } } else{ echo "Oops! Something went wrong. Please try again later."; } } // Close statement mysqli_stmt_close($stmt); } // Validate password if(empty(trim($_POST['password']))){ $password_err = "Please enter a password."; } elseif(strlen(trim($_POST['password'])) < 6){ $password_err = "Password must have atleast 6 characters."; } else{ $password = trim($_POST['password']); } // Validate confirm password if(empty(trim($_POST["confirm_password"]))){ $confirm_password_err = 'Please confirm password.'; } else{ $confirm_password = trim($_POST['confirm_password']); if($password != $confirm_password){ $confirm_password_err = 'Password did not match.'; } } // Check input errors before inserting in database if(empty($username_err) && empty($password_err) && empty($confirm_password_err)){ // Prepare an insert statement $sql = "INSERT INTO users (username, password) VALUES (?, ?)"; if($stmt = mysqli_prepare($link, $sql)){ // Bind variables to the prepared statement as parameters mysqli_stmt_bind_param($stmt, "ss", $param_username, $param_password); // Set parameters $param_username = $username; $param_password = password_hash($password, PASSWORD_DEFAULT); // Creates a password hash // Attempt to execute the prepared statement if(mysqli_stmt_execute($stmt)){ // Redirect to login page header("location: login.php"); } else{ echo "Something went wrong. Please try again later."; } } // Close statement mysqli_stmt_close($stmt); } // Close connection mysqli_close($link); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Sign Up</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"> <style type="text/css"> body{ font: 14px sans-serif; } .wrapper{ width: 350px; padding: 20px; } </style> </head> <body> <div class="wrapper"> <h2>Sign Up</h2> <p>Please fill this form to create an account.</p> <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post"> <div class="form-group <?php echo (!empty($username_err)) ? 'has-error' : ''; ?>"> <label>Username</label> <input type="text" name="username"class="form-control" value="<?php echo $username; ?>"> <span class="help-block"><?php echo $username_err; ?></span> </div> <div class="form-group <?php echo (!empty($password_err)) ? 'has-error' : ''; ?>"> <label>Password</label> <input type="password" name="password" class="form-control" value="<?php echo $password; ?>"> <span class="help-block"><?php echo $password_err; ?></span> </div> <div class="form-group <?php echo (!empty($confirm_password_err)) ? 'has-error' : ''; ?>"> <label>Confirm Password</label> <input type="password" name="confirm_password" class="form-control" value="<?php echo $confirm_password; ?>"> <span class="help-block"><?php echo $confirm_password_err; ?></span> </div> <div class="form-group"> <input type="submit" class="btn btn-primary" value="Submit"> <input type="reset" class="btn btn-default" value="Reset"> </div> <p>Already have an account? <a href="login.php">Login here</a>.</p> </form> </div> </body> </html> |
— The output of the above example (i.e. signup form) should look something like this:
In the above example, we used the PHP password_hash() function to create password hash from the password string entered (line no-75). This function creates a password hash using a strong one-way hashing algorithm. It also generates and applies a random salt automatically when hashing the password; this means that even if two users have the same passwords, their password hashes will be different.
At the time of login, we’ll verify the given password with the password hash stored in the database using the PHP password_verify() function, as demonstrated in the next example. We’ve used the Bootstrap framework to make the form layouts quickly and beautifully.
Tip: Password salting is a technique which is widely used to secure passwords by randomizing password hashes, so that if two users have the same password, they will not have the same password hashes. This is done by appending or prepending a random string, called a salt, to the password before hashing.
Building the Login System
In this section, we’ll create a login form where the user can enter their username and password. When the user submits the form, these inputs will be verified against the credentials stored in the database, if the username and password match, the user is authorized and granted access to the site, otherwise, the login attempt will be rejected.
Step 1: Creating the Login Form
Let’s create a file named “login.php” and place the following code inside it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | <?php // Include config file require_once 'config.php'; // Define variables and initialize with empty values $username = $password = ""; $username_err = $password_err = ""; // Processing form data when form is submitted if($_SERVER["REQUEST_METHOD"] == "POST"){ // Check if username is empty if(empty(trim($_POST["username"]))){ $username_err = 'Please enter username.'; } else{ $username = trim($_POST["username"]); } // Check if password is empty if(empty(trim($_POST['password']))){ $password_err = 'Please enter your password.'; } else{ $password = trim($_POST['password']); } // Validate credentials if(empty($username_err) && empty($password_err)){ // Prepare a select statement $sql = "SELECT username, password FROM users WHERE username = ?"; if($stmt = mysqli_prepare($link, $sql)){ // Bind variables to the prepared statement as parameters mysqli_stmt_bind_param($stmt, "s", $param_username); // Set parameters $param_username = $username; // Attempt to execute the prepared statement if(mysqli_stmt_execute($stmt)){ // Store result mysqli_stmt_store_result($stmt); // Check if username exists, if yes then verify password if(mysqli_stmt_num_rows($stmt) == 1){ // Bind result variables mysqli_stmt_bind_result($stmt, $username, $hashed_password); if(mysqli_stmt_fetch($stmt)){ if(password_verify($password, $hashed_password)){ /* Password is correct, so start a new session and save the username to the session */ session_start(); $_SESSION['username'] = $username; header("location: welcome.php"); } else{ // Display an error message if password is not valid $password_err = 'The password you entered was not valid.'; } } } else{ // Display an error message if username doesn't exist $username_err = 'No account found with that username.'; } } else{ echo "Oops! Something went wrong. Please try again later."; } } // Close statement mysqli_stmt_close($stmt); } // Close connection mysqli_close($link); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"> <style type="text/css"> body{ font: 14px sans-serif; } .wrapper{ width: 350px; padding: 20px; } </style> </head> <body> <div class="wrapper"> <h2>Login</h2> <p>Please fill in your credentials to login.</p> <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post"> <div class="form-group <?php echo (!empty($username_err)) ? 'has-error' : ''; ?>"> <label>Username</label> <input type="text" name="username"class="form-control" value="<?php echo $username; ?>"> <span class="help-block"><?php echo $username_err; ?></span> </div> <div class="form-group <?php echo (!empty($password_err)) ? 'has-error' : ''; ?>"> <label>Password</label> <input type="password" name="password" class="form-control"> <span class="help-block"><?php echo $password_err; ?></span> </div> <div class="form-group"> <input type="submit" class="btn btn-primary" value="Login"> </div> <p>Don't have an account? <a href="register.php">Sign up now</a>.</p> </form> </div> </body> </html> |
— The output of the above example (i.e. login form) should look something like this:
Step 2: Creating the Welcome Page
Here’s the code of our “welcome.php” file, where the user is redirected after successful login.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <?php // Initialize the session session_start(); // If session variable is not set it will redirect to login page if(!isset($_SESSION['username']) || empty($_SESSION['username'])){ header("location: login.php"); exit; } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Welcome</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css"> <style type="text/css"> body{ font: 14px sans-serif; text-align: center; } </style> </head> <body> <div class="page-header"> <h1>Hi, <b><?php echo htmlspecialchars($_SESSION['username']); ?></b>. Welcome to our site.</h1> </div> <p><a href="logout.php" class="btn btn-danger">Sign Out of Your Account</a></p> </body> </html> |
If data comes from external sources like form filled in by anonymous users, there is a risk that it may contain malicious script indented to launch cross-site scripting (XSS) attacks. Therefore, you must escape this data using the PHP htmlspecialchars() function before displaying it in the browser, so that any HTML tag it contains becomes harmless.
For example, after escaping special characters the string <script>alert("XSS")</script>
becomes <script>alert("XSS")</script>
which is not executed by the browser.
Step 3: Creating the Logout Script
Finally, we need to create a “logout.php” file. When the user clicks on the logout or signout links, the script inside this file destroys the session and redirects the user back to the login page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php // Initialize the session session_start(); // Unset all of the session variables $_SESSION = array(); // Destroy the session. session_destroy(); // Redirect to login page header("location: login.php"); exit; ?> |
Enjoy!