DEV Community

Cover image for PHP crash course : Simple User Authentication System
MD ARIFUL HAQUE
MD ARIFUL HAQUE

Posted on

PHP crash course : Simple User Authentication System

A basic user registration and login system built with PHP, HTML, jQuery, AJAX, JSON, Bootstrap, CSS, and MySQL. This project demonstrates a simple yet secure way to handle user authentication, including registration, login, and session management.

Topics: php, mysql, ajax, json, bootstrap, jquery, css, user authentication, user registration, user-login, session management

Step-by-Step Solution

1. Directory Structure

simple-user-authentication-system/ │ ├── backend/ │ └── index.php │ ├── assets/ │ ├── css/ │ │ └── style.css │ └── js/ │ └── script.js │ ├── db/ │ └── database.sql │ ├── includes/ │ ├── config.sample.php │ ├── db.php │ ├── login.php │ ├── logout.php │ └── register.php │ ├── src/ │ ├── login.php │ ├── logout.php │ └── register.php │ ├── index.html ├── register.html ├── login.html ├── README.md └── .gitignore 
Enter fullscreen mode Exit fullscreen mode

2. Database Schema

db/database.sql:

CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `email` VARCHAR(100) NOT NULL UNIQUE, `password` varchar(255) NOT NULL, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
Enter fullscreen mode Exit fullscreen mode

3. Configuration File

Configuration settings (include/config.sample.php)

<?php // Database configuration define('DB_HOST', 'localhost'); // Database host define('DB_NAME', 'user_authentication'); // Database name define('DB_USER', 'root'); // Change if necessary define('DB_PASS', ''); // Change if necessary ?> 
Enter fullscreen mode Exit fullscreen mode

4. Configure the Database Connection

Establishing database connection (include/db.php)

<?php include 'db.php'; // Database configuration $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; // Create a new PDO instance try { $pdo = new PDO($dsn, DB_USER, DB_PASS, $options); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Set error mode to exception } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); // Display error message if connection fails } ?> 
Enter fullscreen mode Exit fullscreen mode

5. HTML and PHP Structure

HTML Structure (index.html)

home

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Home</title> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <div class="wrapper"> <h1>Welcome, Guest!</h1> <a href="login.html">Login</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<a href="register.html">Sign up</a> </div> </body> </html> 
Enter fullscreen mode Exit fullscreen mode

Registration User Structure (register.html)

register

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Sign Up</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <div class="wrapper"> <h2>Sign Up</h2> <p>Please fill this form to create an account.</p> <span class="message"></span> <form id="registerForm"> <div class="form-group"> <label>Username</label> <input type="text" name="username" class="form-control"> <span class="help-block username"></span> </div> <div class="form-group"> <label for="email">Email:</label> <input type="email" class="form-control" id="email" name="email"> <span class="help-block email"></span> </div> <div class="form-group"> <label>Password</label> <input type="password" name="password" class="form-control"> <span class="help-block password"></span> </div> <div class="form-group"> <label>Confirm Password</label> <input type="password" name="confirm_password" class="form-control"> <span class="help-block confirm_password"></span> </div> <div class="form-group"> <input type="submit" class="btn btn-primary" value="Submit"> </div> <p>Already have an account? <a href="login.html">Login here</a>.</p> </form> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <script src="assets/js/script.js"></script> </body> </html> 
Enter fullscreen mode Exit fullscreen mode

(src/register.php)

<?php require_once '../include/register.php'; $username = $password = $confirm_password= $email = ""; $response = []; $response['status'] = true; if($_SERVER["REQUEST_METHOD"] == "POST") { if(empty(trim($_POST["username"]))) { $response['status'] = false; $response['field'] = 'username'; $response['message'] = "Please enter a username."; } elseif(empty(trim($_POST["email"]))) { $response['status'] = false; $response['field'] = 'email'; $response['message'] = "Please enter a email."; } elseif(empty(trim($_POST["password"]))) { $response['status'] = false; $response['field'] = 'password'; $response['message'] = "Please enter a password."; } elseif(strlen(trim($_POST["password"])) < 6) { $response['status'] = false; $response['field'] = 'password'; $response['message'] = "Password must have at least 6 characters."; } elseif(empty(trim($_POST["confirm_password"]))) { $response['status'] = false; $response['field'] = 'confirm_password'; $response['message'] = "Please confirm password."; } elseif(trim($_POST["password"]) != trim($_POST["confirm_password"])) { $response['status'] = false; $response['field'] = 'confirm_password'; $response['message'] = "Password did not match."; }else { $username = trim($_POST["username"]); $email = trim($_POST["email"]); $password = trim($_POST["password"]); $confirm_password = trim($_POST["confirm_password"]); $password_hash = password_hash($password, PASSWORD_DEFAULT); $response = register_user($username, $email, $password_hash); } } echo json_encode($response); ?> 
Enter fullscreen mode Exit fullscreen mode

(include/register.php)

<?php require_once 'db.php'; /** * @param $username * @param $email * @param $password * @return array */ function register_user($username, $email, $password) { global $pdo; $response = []; $response['status'] = true; // Check if the username already exists $sql = "SELECT id FROM users WHERE username = :username OR email = :email"; if($stmt = $pdo->prepare($sql)) { $stmt->bindParam(":username", $username, PDO::PARAM_STR); $stmt->bindParam(":email", $email, PDO::PARAM_STR); if($stmt->execute()) { if($stmt->rowCount() == 1) { $response['status'] = false; $response['message'] = "Username or email already exists."; } else { // Username is available, so insert the new user $sql = "INSERT INTO users (username, email, password) VALUES (:username, :email, :password)"; if($stmt = $pdo->prepare($sql)) { // Bind variables to the prepared statement $stmt->bindParam(":username", $username, PDO::PARAM_STR); $stmt->bindParam(":email", $email, PDO::PARAM_STR); $stmt->bindParam(":password", $password, PDO::PARAM_STR); // Attempt to execute the prepared statement if($stmt->execute()) { $response['message'] = "Registration successful!"; } else { $response['status'] = false; $response['message'] = "Something went wrong. Please try again later."; } }else{ $response['status'] = false; $response['message'] = 'Registration failed. Please try again.'; } } } else { $response['status'] = false; $response['message'] = "Oops! Something went wrong. Please try again later."; } } unset($stmt); unset($pdo); return $response; } 
Enter fullscreen mode Exit fullscreen mode

Login User Structure (index.html)

login

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Home</title> <link rel="stylesheet" href="assets/css/style.css"> </head> <body> <div class="wrapper"> <h1>Welcome, Guest!</h1> <a href="login.html">Login</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<a href="register.html">Sign up</a> </div> </body> </html> 
Enter fullscreen mode Exit fullscreen mode

(src/login.php)

<?php require_once '../include/login.php'; $result = []; if($_SERVER["REQUEST_METHOD"] == "POST") { $username = trim($_POST['username']); $password = trim($_POST['password']); // Check for empty fields if (empty($username) || empty($password)) { $response['status'] = false; $response['message'] = 'Please fill in all fields.'; } else { $result = login_user($username, $password); } echo json_encode($result); } ?> ?> 
Enter fullscreen mode Exit fullscreen mode

(include/login.php)

<?php <?php require_once 'db.php'; /** * @param $username * @param $password * @return array */ function login_user($username, $password) { global $pdo; $response = array(); $sql = "SELECT id, username, password FROM users WHERE username = :username"; if($stmt = $pdo->prepare($sql)) { $stmt->bindParam(":username", $username, PDO::PARAM_STR); if($stmt->execute()) { if($stmt->rowCount() == 1) { if($row = $stmt->fetch()) { $id = $row["id"]; $username = $row["username"]; $hashed_password = $row["password"]; if(password_verify($password, $hashed_password)) { // Password is correct, start a new session session_start(); $_SESSION["loggedin"] = true; $_SESSION["id"] = $id; $_SESSION["username"] = $username; $response['status'] = true; $response['message'] = 'Login successful!'; } else { $response['status'] = false; $response['message'] = 'The password you entered was not valid.'; } } } else { $response['status'] = false; $response['message'] = 'No account found with that username.'; } } else { $response['status'] = false; $response['message'] = 'Oops! Something went wrong. Please try again later.'; } } unset($stmt); unset($pdo); return $response; } 
Enter fullscreen mode Exit fullscreen mode

After Login User Structure (backend/index.php)

after-login

<?php session_start(); if (!isset($_SESSION['username'])) { header('Location: ../index.html'); exit(); } ?> 
Enter fullscreen mode Exit fullscreen mode
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Home</title> <link rel="stylesheet" href="../assets/css/style.css"> </head> <body> <div class="wrapper"> <h1>Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?>!</h1> <a href="../src/logout.php">Logout</a> </div> </body> </html> 
Enter fullscreen mode Exit fullscreen mode

Logout (src/logout.php)

<?php require_once '../include/logout.php'; logout_user(); ?> 
Enter fullscreen mode Exit fullscreen mode

(include/logout.php)

<?php require_once 'db.php'; /** * @return void */ function logout_user() { session_start(); $_SESSION = array(); session_destroy(); header("location: ../backend/index.php"); exit; } 
Enter fullscreen mode Exit fullscreen mode

6. JavaScript and AJAX

AJAX Handling (assets/js/script.js)

$(document).ready(function() { $('.help-block').hide(); $("#registerForm").submit(function(event) { event.preventDefault(); $('.help-block').hide(); $.ajax({ url: "src/register.php", type: "post", dataType: 'json', data: $(this).serialize(), success: function(response) { if(response.status === false){ if(response.field){ $('.' + response.field).show(); $('.' + response.field).html(response.message); }else{ $('.message').html(response.message); } }else{ $('#registerForm')[0].reset(); $('#registerForm').hide(); $('h2').hide(); $('p').html(response.message + ' <a href="login.html">Please Login here</a>'); //window.location.href = 'index.html'; } } }); }); $("#loginForm").submit(function(event) { event.preventDefault(); $.ajax({ url: "src/login.php", type: "post", dataType: 'json', data: $(this).serialize(), success: function(response) { if (response.status === true) { window.location.href = 'backend/index.php'; } } }); }); }); 
Enter fullscreen mode Exit fullscreen mode

7. Stylesheet (assets/css/style.css)

body { font: 14px sans-serif; } .wrapper { width: 350px; padding: 20px; margin: 0 auto; } .help-block { color: red; } 
Enter fullscreen mode Exit fullscreen mode

Documentation and Comments

Each part of the code has been commented to explain what it does:

  • include/config.php: Contains the database connection configuration.
  • include/register.php: Contains helper functions for registering, logging in, and logging out users.
  • include/login.php: Contains helper functions for registering, logging in, and logging out users.
  • include/logout.php: Contains helper functions for registering, logging in, and logging out users.
  • src/register.php: Handles user registration, including form validation and submission via AJAX.
  • src/login.php: Handles user login, including form validation and submission via AJAX.
  • src/logout.php: Handles user logout.
  • assets/css/style.css: Contains basic styles for the pages.
  • assets/js/script.js: Contains the jQuery AJAX functions for handling form submissions.

This project setup and code should help you create a basic user authentication system.

Connecting Links

If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

Source Code

Top comments (0)