PHP crash course : Simple User Authentication System

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

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;

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
?>

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
}
?>

5. HTML and PHP Structure

HTML Structure (index.html)

<!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>

Registration User Structure (register.html)

<!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>

(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);
?>

(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;
}

Login User Structure (index.html)

<!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>

(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);
}
?>

?>

(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;
}

After Login User Structure (backend/index.php)

<?php
session_start();
if (!isset($_SESSION[‘username’])) {
header(‘Location: ../index.html’);
exit();
}
?>
<!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>

Logout (src/logout.php)

<?php
require_once ‘../include/logout.php’;
logout_user();
?>

(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;
}

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;
}
}
});
});
});

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

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

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:

LinkedIn
GitHub

Source Code

Please follow and like us:
Pin Share