Creating a secure login system is a crucial part of any web application. This tutorial will guide you through the process of building a secure PHP login system using Bootstrap 5 for styling, a MySQL database for user data storage, and CSS animations for a smooth user experience.
Prerequisites
Before we start, ensure you have the following:
A web server with PHP and MySQL installed (e.g., XAMPP, WAMP, LAMP).
Basic knowledge of PHP, MySQL, HTML, and CSS.
Bootstrap 5 library.
Step 1: Setting Up the Project
Create the project directory structure:
secure-login/
├── css/
│ └── styles.css
├── js/
├── index.php
├── login.php
├── register.php
├── welcome.php
└── config.php
Download and include Bootstrap 5:
Add the following Bootstrap CDN links in your index.php, login.php, register.php, and welcome.php files:
<link href="https://stackpath.bootstrapcdn.com/bootstrap/5.1.3/css/bootstrap.min.css" rel="stylesheet">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
Create a database and user table:
CREATE DATABASE secure_login;
USE secure_login;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Step 2: Configuration File
Create config.php to handle database connections:
<?php
$servername = "localhost";
$username = "root"; // DB username
$password = "root"; // DB password
$dbname = "secure_login";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
?>
Step 3: Registration Form
Create register.php for new users to sign up:
<?php
require_once "config.php";
$username = $password = "";
$username_err = $password_err = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty(trim($_POST["username"]))) {
$username_err = "Please enter a username.";
} else {
$sql = "SELECT id FROM users WHERE username = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param("s", $param_username);
$param_username = trim($_POST["username"]);
if ($stmt->execute()) {
$stmt->store_result();
if ($stmt->num_rows == 1) {
$username_err = "This username is already taken.";
} else {
$username = trim($_POST["username"]);
}
} else {
echo "Oops! Something went wrong. Please try again later.";
}
$stmt->close();
}
}
if (empty(trim($_POST["password"]))) {
$password_err = "Please enter a password.";
} else {
$password = trim($_POST["password"]);
}
if (empty($username_err) && empty($password_err)) {
$sql = "INSERT INTO users (username, password) VALUES (?, ?)";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param("ss", $param_username, $param_password);
$param_username = $username;
$param_password = password_hash($password, PASSWORD_DEFAULT);
if ($stmt->execute()) {
header("location: login.php");
} else {
echo "Something went wrong. Please try again later.";
}
$stmt->close();
}
}
$conn->close();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Register</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="wrapper">
<h2>Register</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">
<span class="help-block"><?php echo $password_err; ?></span>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Submit">
</div>
<p>Already have an account? <a href="login.php">Login here</a>.</p>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script>
</body>
</html>
Step 4: Login Form
Create login.php for user authentication:
<?php
session_start();
require_once "config.php";
$username = $password = "";
$username_err = $password_err = $login_err = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty(trim($_POST["username"]))) {
$username_err = "Please enter username.";
} else {
$username = trim($_POST["username"]);
}
if (empty(trim($_POST["password"]))) {
$password_err = "Please enter your password.";
} else {
$password = trim($_POST["password"]);
}
if (empty($username_err) && empty($password_err)) {
$sql = "SELECT id, username, password FROM users WHERE username = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param("s", $param_username);
$param_username = $username;
if ($stmt->execute()) {
$stmt->store_result();
if ($stmt->num_rows == 1) {
$stmt->bind_result($id, $username, $hashed_password);
if ($stmt->fetch()) {
if (password_verify($password, $hashed_password)) {
session_start();
$_SESSION["loggedin"] = true;
$_SESSION["id"] = $id;
$_SESSION["username"] = $username;
header("location: welcome.php");
} else {
$login_err = "Invalid username or password.";
}
}
} else {
$login_err = "Invalid username or password.";
}
} else {
echo "Oops! Something went wrong. Please try again later.";
}
$stmt->close();
}
}
$conn->close();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="wrapper">
<h2>Login</h2>
<p>Please fill in your credentials to login.</p>
<?php
if(!empty($login_err)){
echo '<div class="alert alert-danger">' . $login_err . '</div>';
}
?>
<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>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script>
</body>
</html>
Step 5: Welcome Page
Create welcome.php to display after successful login:
<?php
session_start();
if(!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true){
header("location: login.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"></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>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-0pUGZvbkm6XF6gxjEnlmuGrJXVbNuzT9qBBavbLwCsOGabYfZo0T0to5eqruptLy" crossorigin="anonymous"></script>
</body>
</html>
Step 6: CSS Animations
Add CSS animations in styles.css:
body {
font: 14px sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #f8f9fa;
}
.wrapper {
width: 360px;
padding: 20px;
background: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
animation: fadeIn 1.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
Step 7: Logout
Create logout.php to handle user logout:
<?php
session_start();
$_SESSION = array();
session_destroy();
header("location: login.php");
exit;
?>
You've now created a secure PHP login system with Bootstrap 5, MySQL, and CSS animations. This setup provides a basic structure that you can expand upon by adding more features such as email verification, password recovery, and user profile management. Remember to always prioritize security and follow best practices to protect user data.
Secure your internet connection instantly with NordVPN and enjoy 3 extra months free on any plan. Whether you’re browsing, streaming, or gaming, NordVPN keeps your data safe from prying eyes. Don’t wait—protect your privacy and save big today!