Secure login system is crucial part of managing user data. In this tutorial we are going to implement login system with use PDO prepared statement and PHP. It also helps for targets brute force, SQL injection, and session hijacking attacks. without implementing secure login functionality, your site may risk for attack. This login scripts includes:
- SEO friendly URL using .htaccess
- Secure auth using password_hash() function.
- MVC base coding standard.
- SQL injection preventing using PDO prepared statement.
- Session management and redirect
- MVC coding with includes login, logout and dashboard.
Why secure login is important?
Without implementation of proper security web application get stuck any time and effecting malware. at the end resulting loss of all site. to prevent all this, we use PDO Prepared statements, session handling and password hashing functions.
Database Setup for Secure Authentication
CREATE TABLE `users` ( `id` int(11) NOT NULL, `username` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `email_address` varchar(255) NOT NULL, `user_role` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ALTER TABLE `users` ADD PRIMARY KEY (`id`); ALTER TABLE `users` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT
Insert dummy data for testing purpose.
INSERT INTO `users` (`id`, `username`, `password`, `email_address`, `user_role`) VALUES (1, '[email protected]', '$2y$04$x.Leg9GtLYPmw0G7rZZZj.ARrhblZxVR7W33cmhqW316F2iLKMz1.', '[email protected]', 'ADMIN');
Project File Structure
📄 .htaccess 📁 config │ 📄 config.php 📁 controller │ 📄 authcontroller.php │ 📄 basecontroller.php 📄 index.php 📁 models │ 📄 user.php 📁 view │ 📄 dashboard.php │ 📄 layout.php │ 📄 login.php │ 📄 topbar.php
Create database connection(config.php)
<?php ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); class Database { public static function connect() { static $conn; if (!$conn) { $conn = new PDO("mysql:host=127.0.0.1:3360;dbname=new_programmerdesk", "root", ""); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } return $conn; } } session_start(); ?>
Index.php helps for redirect user request to proper controller, in our example we can login, logout and dashboard for SEO friendly URL.
Create Routing with index.php
<?php include('config/config.php'); include('controller/basecontroller.php'); include('controller/authcontroller.php'); $url = isset($_GET['url']) ? explode('/', trim($_GET['url'], '/')) : []; $controller=new authcontroller(); switch($url[0]??''){ case 'login': $_SERVER['REQUEST_METHOD'] === 'POST' ? $controller->login($_POST) : $controller->showlogin(); break; case 'dashboard': $controller->dashboard(); break; case 'logout': $controller->logout(); break; } ?>
Let’s create authcontroller.php which handle all business logic.
- __construct()
Call user Model class which helps for retrieve data.
- showlogin()
Pass page name and display HTML view.
- login()
Pass user form data to login method it helps for validate user if exists and we can use Password Hashing using password_hash()
and password_verify()
Create Auth Controller (authcontroller.php)
<?php require_once __DIR__ . '/../models/user.php'; class authcontroller extends basecontroller{ private $user; public function __construct(){ $this->user=new user(); } public function showlogin($error=''){ $page="login"; $this->view($page, compact('error')); } public function login($post){ $username = trim($post['email']); $password = $post['password']; $user = $this->user->finduser($username); if ($user && password_verify($password, $user['password'])) { session_regenerate_id(true); $_SESSION['user'] = $user['id']; header("Location: dashboard"); exit; } else { $error[] = "Invalid email or password."; $this->showlogin($error); } } public function dashboard(){ $this->redirect(); $page="dashboard"; $this->view($page); } public function logout(){ session_destroy(); header("Location: login"); } }
Base Controller (basecontroller.php)
<?php class basecontroller{ protected function view($page, $error=[]){ extract($error); include __DIR__ . '/../view/layout.php'; } protected function redirect(){ if(!isset($_SESSION['user'])){ header("location:login"); exit; } } }
Create user model(user.php)
<?php require_once __DIR__ . '/../config/config.php'; class user{ private $conn; public function __construct(){ $this->conn= Database::connect(); } public function finduser($username){ $stmt = $this->conn->prepare("SELECT * FROM users WHERE email = ?"); $stmt->execute([$username]); return $stmt->fetch(PDO::FETCH_ASSOC); } }
Create one common layout which helps for displaying all pages. in our case we can create login page, dashboard page.
Create layout.php
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" crossorigin="anonymous"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" crossorigin="anonymous"> <style> .account-col { width: 300px; margin: 0 auto; text-align: center; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" crossorigin="anonymous"></script> </head> <body> <div class="container"> <?php if(isset($_SESSION['user'])){ include "view/topbar.php"; } ?> <div class="row"> <div class="account-col text-center"> <?php if (!empty($page) && file_exists("view/$page.php")) { include "view/$page.php"; } ?> </div> </div> </div> </body> </html>
Inside View Create login page call as login.php
<h3>Log into your account</h3> <form class="m-t" role="form" method="post" action="login"> <div class="form-group"> <input type="text" class="form-control" name="email" placeholder="Email" required=""> </div> <div class="form-group"> <input type="password" class="form-control" name="password" placeholder="Passowrd" required=""> </div> <button type="submit" class="btn btn-primary btn-block ">Login</button> <div class="form-group login-input"> <span style="color: #b70a0a;"><?php if(!empty($error)){ echo "Your Email or Password is invalid"; } ?></span> </div> </form>
Output
Final output of login, if user authenticate successfully. next if you want to extends this login functionality with forgot password refer it from here ?

Conclusion.
This guide you, for build robust, efficient and MVC based login clean code system. With prepared statements, session handling, and password hashing, this is a robust starting point for any PHP-based application.
Download View