PHP – Use Case 2: Implementing a User Authentication System (Registration and Login)
Project Overview
A User Authentication System allows users to register, log in, and access protected areas of a website. This project covers user registration, login, session management, password hashing, and access control using PHP and MySQL.
Prerequisites
Ensure you have the following:
- Web Server: Apache (using XAMPP, WAMP, or MAMP)
- PHP: Version 7.4 or higher
- MySQL: For database management
- Code Editor: VS Code, Sublime Text, PHPStorm, etc.
- Composer: For dependency management (optional)
Step-by-Step Procedure
1. Setting Up the Development Environment
- Install XAMPP:
- Download from XAMPP Official Website.
- Follow the installation wizard and install it in the default directory.
- Start Apache and MySQL:
- Open the XAMPP Control Panel.
- Start the Apache and MySQL modules.
2. Creating the Database
- Access phpMyAdmin:
- Navigate to
http://localhost/phpmyadmin/
in your browser.
- Navigate to
- Create a New Database:
- Click on “New” in the left sidebar.
- Name the database
user_auth
. - Choose “utf8mb4_unicode_ci” as the collation.
- Click “Create”.
- Create a
users
Table:- Select the
user_auth
database. - Click on “New” to create a table.
- Define the table with the following fields:
- Click “Save”.
- Select the
3. Project Structure
Organize your project files as follows:
user-auth/
├── assets/
│ ├── css/
│ │ └── styles.css
│ └── js/
│ └── scripts.js
├── config/
│ └── db.php
├── templates/
│ ├── header.php
│ └── footer.php
├── register.php
├── login.php
├── logout.php
├── dashboard.php
└── README.md
4. Configuration
a. Database Connection (config/db.php
)
<?php
// config/db.php
$host = 'localhost';
$db = 'user_auth';
$user = 'root'; // Default XAMPP MySQL user
$pass = ''; // Default XAMPP MySQL password is empty
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // Enable exceptions
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // Fetch associative arrays
PDO::ATTR_EMULATE_PREPARES => false, // Disable emulation
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
// Handle connection errors
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>
5. Creating Reusable Templates
a. Header (templates/header.php
)
<?php
// templates/header.php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User Authentication System</title>
<link rel="stylesheet" href="/user-auth/assets/css/styles.css">
</head>
<body>
<header>
<h1>User Authentication System</h1>
<nav>
<?php if (isset($_SESSION['user_id'])): ?>
<a href="/user-auth/dashboard.php">Dashboard</a>
<a href="/user-auth/logout.php">Logout</a>
<?php else: ?>
<a href="/user-auth/login.php">Login</a>
<a href="/user-auth/register.php">Register</a>
<?php endif; ?>
</nav>
</header>
<main>
b. Footer (templates/footer.php
)
<?php
// templates/footer.php
?>
</main>
<footer>
<p>© <?php echo date("Y"); ?> Your Company Name</p>
</footer>
<script src="/user-auth/assets/js/scripts.js"></script>
</body>
</html>
6. Styling the Application (assets/css/styles.css
)
Add basic styles to enhance the appearance.
/* assets/css/styles.css */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
header, footer {
background-color: #444;
color: #fff;
padding: 10px 20px;
}
header h1, footer p {
margin: 0;
}
nav a {
color: #fff;
margin-right: 15px;
text-decoration: none;
}
main {
padding: 20px;
}
form {
max-width: 400px;
margin: auto;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="email"],
input[type="password"] {
width: 100%;
padding: 8px;
box-sizing: border-box;
}
button {
padding: 10px 15px;
background-color: #007BFF;
color: #fff;
border: none;
cursor: pointer;
}
button:hover {
background-color: #0069d9;
}
.error {
background-color: #f2dede;
color: #a94442;
padding: 15px;
margin-bottom: 20px;
border: 1px solid #ebccd1;
border-radius: 4px;
}
.success {
background-color: #dff0d8;
color: #3c763d;
padding: 15px;
margin-bottom: 20px;
border: 1px solid #d6e9c6;
border-radius: 4px;
}
7. User Registration (register.php
)
This page allows new users to create an account.
<?php
// register.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate inputs
$username = trim($_POST['username']);
$email = trim($_POST['email']);
$password = trim($_POST['password']);
$confirm_password = trim($_POST['confirm_password']);
// Validation
if (empty($username)) {
$errors[] = 'Username is required.';
}
if (empty($email)) {
$errors[] = 'Email is required.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format.';
}
if (empty($password)) {
$errors[] = 'Password is required.';
} elseif (strlen($password) < 6) {
$errors[] = 'Password must be at least 6 characters.';
}
if ($password !== $confirm_password) {
$errors[] = 'Passwords do not match.';
}
// Check if username or email already exists
if (empty($errors)) {
$stmt = $pdo->prepare('SELECT id FROM users WHERE username = ? OR email = ?');
$stmt->execute([$username, $email]);
if ($stmt->fetch()) {
$errors[] = 'Username or email already exists.';
}
}
if (empty($errors)) {
// Hash the password
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
// Insert into database
$stmt = $pdo->prepare('INSERT INTO users (username, email, password) VALUES (?, ?, ?)');
if ($stmt->execute([$username, $email, $hashed_password])) {
$success = 'Registration successful. You can now <a href="login.php">login</a>.';
// Clear form fields
$username = $email = $password = $confirm_password = '';
} else {
$errors[] = 'There was an error registering. Please try again.';
}
}
}
?>
<h2>Register</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<p><?php echo $success; ?></p>
</div>
<?php endif; ?>
<form action="register.php" method="POST">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" value="<?php echo htmlspecialchars($username ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" value="<?php echo htmlspecialchars($email ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="password">Password (min 6 characters):</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label for="confirm_password">Confirm Password:</label>
<input type="password" id="confirm_password" name="confirm_password" required>
</div>
<button type="submit">Register</button>
</form>
<?php
require 'templates/footer.php';
?>
8. User Login (login.php
)
This page allows existing users to log in.
<?php
// login.php
require 'config/db.php';
require 'templates/header.php';
$errors = [];
$success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Sanitize and validate inputs
$username = trim($_POST['username']);
$password = trim($_POST['password']);
if (empty($username)) {
$errors[] = 'Username is required.';
}
if (empty($password)) {
$errors[] = 'Password is required.';
}
if (empty($errors)) {
// Fetch user from database
$stmt = $pdo->prepare('SELECT id, password FROM users WHERE username = ?');
$stmt->execute([$username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password'])) {
// Password is correct, start a session
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $username;
// Redirect to dashboard
header('Location: dashboard.php');
exit;
} else {
$errors[] = 'Invalid username or password.';
}
}
}
?>
<h2>Login</h2>
<?php if (!empty($errors)): ?>
<div class="error">
<ul>
<?php foreach($errors as $error): ?>
<li><?php echo htmlspecialchars($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="success">
<p><?php echo htmlspecialchars($success); ?></p>
</div>
<?php endif; ?>
<form action="login.php" method="POST">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" value="<?php echo htmlspecialchars($username ?? ''); ?>" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
<?php
require 'templates/footer.php';
?>
9. User Dashboard (dashboard.php
)
This is a protected page accessible only to logged-in users.
<?php
// dashboard.php
require 'config/db.php';
require 'templates/header.php';
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
// Fetch user information
$stmt = $pdo->prepare('SELECT username, email, created_at FROM users WHERE id = ?');
$stmt->execute([$_SESSION['user_id']]);
$user = $stmt->fetch();
?>
<h2>Welcome, <?php echo htmlspecialchars($user['username']); ?>!</h2>
<p>Email: <?php echo htmlspecialchars($user['email']); ?></p>
<p>Member since: <?php echo htmlspecialchars($user['created_at']); ?></p>
<?php
require 'templates/footer.php';
?>
10. User Logout (logout.php
)
This script logs the user out by destroying the session.
<?php
// logout.php
session_start();
session_unset();
session_destroy();
// Redirect to login page
header('Location: login.php');
exit;
?>
11. Testing the Application
- Access the Registration Page:
- Navigate to
http://localhost/user-auth/register.php
. - Fill in the registration form and submit.
- Verify that the user is registered and redirected appropriately.
- Navigate to
- Access the Login Page:
- Navigate to
http://localhost/user-auth/login.php
. - Enter the registered credentials and log in.
- Verify access to the dashboard.
- Navigate to
- Access Protected Page:
- Navigate to
http://localhost/user-auth/dashboard.php
. - Ensure that only logged-in users can access this page.
- Navigate to
- Logout:
- Click on “Logout”.
- Verify that the session is destroyed and access to the dashboard is restricted.
12. Deployment Considerations
When deploying to a live server:
- Secure Database Credentials: Use environment variables or secure configuration methods.
- Use HTTPS: Ensure your website uses HTTPS for encrypted data transmission.
- Regular Backups: Implement regular backups of your database and files.
- Error Reporting: Disable detailed error messages in production to prevent information leakage.
// In production, set error reporting to minimal ini_set('display_errors', 0); ini_set('log_errors', 1);
- Update Dependencies: Keep PHP and all libraries updated to their latest versions to patch security vulnerabilities.
- Implement Strong Password Policies: Enforce strong passwords and consider adding features like password reset via email.