Hi in this tutorial we gonna learn how to login securely in PHP this is a different type of login functionality you can protect the page and only the admin can register a new user and the admin give a username password to login so let's write a code and understand it.
We need two tables of database one is accounts and another is auth_admin. see the database structure below
Database structure
-- phpMyAdmin SQL Dump
-- version 5.0.4
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Apr 07, 2021 at 05:13 AM
-- Server version: 10.4.17-MariaDB
-- PHP Version: 7.4.14
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
--
-- Database: `phplogin`
--
-- --------------------------------------------------------
--
-- Table structure for table `accounts`
--
CREATE TABLE `accounts` (
`id` int(11) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(100) NOT NULL,
`non_enc_pass` varchar(300) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `accounts`
--
INSERT INTO `accounts` (`id`, `username`, `password`, `email`, `non_enc_pass`) VALUES
(7, 'rathorji', '$2y$10$1sNJ9S0reHWeNKOyyuJUL.AQFsSl/CHnd1rfg.k1aouB0xTwLCmuK', 'gajanand.kgn@gmail.com', 'rathorji'),
(8, 'orchid', '$2y$10$yR8g/XeBYwKmsEueVC/YM.4sXBrvBmHpH4Os0zDF34h0fLFIlekcy', 'orchid@gmail.com', 'test'),
(9, 'mandal', '$2y$10$D0uSJYP7eDCwEGAJcb9vP.5uSUD6XisgZnlgdAWkzdlYBMtTjKhwK', 'mandal@gmail.com', 'test'),
(10, 'rakesh', '$2y$10$Ml8x9ab5LknGGZU62d13Ee.gAJDvEqixJbtA6mAkYkad9baKhGi5e', 'rakesh@gmail.com', 'rakesh'),
(11, 'dummy', '$2y$10$TzU8Kf0AF1SmndEsK7JF.ObKLlJQkVw0GQ1ABbXZOXn0gvhBFJy1O', 'dummy@gmail.com', 'dummmyuser'),
(12, 'test', '$2y$10$awtJ2zGEhsow7.Nd0NtTMeUsPXfQnMc3rvNX1NtCkp6SVzdHhF8cS', 'test@gmail.com', 'test'),
(13, 'another', '$2y$10$BQQWkCw0mpSZVLwukB81ruQcJMJi9rw2vxj3XQ730TdNPXWYHNI7i', 'another@gmail.com', 'another'),
(14, 'website', '$2y$10$mVUYVH6pYsBpOHyYG7u71eZvXGMZvwuhSrWkE27mbo0uocTuEQ5xG', 'website@gmail.com', 'test'),
(15, 'testing_user', '$2y$10$HyRH.K0YfhKd/91lyb5GAetOcTd/z6UDsTBxkOSDB2Y4U6XNgwsRu', 'testing@gmail.com', 'aohter password'),
(16, 'stint', '$2y$10$1SYcPy5t8C9sURcJZSlrlewrARwRRifWbAGQeZMcPLg6UU.xEgCfq', 'gajanand.kgn@rediffmail.com', 'stint');
-- --------------------------------------------------------
--
-- Table structure for table `auth_admin`
--
CREATE TABLE `auth_admin` (
`id` int(11) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `auth_admin`
--
INSERT INTO `auth_admin` (`id`, `username`, `password`, `email`) VALUES
(1, 'test', '$2y$10$SfhYIDtn.iOuCW7zfoFLuuZHX6lja4lF4XA4JqNmpiH/.P3zB8JCa', 'test@test.com');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `accounts`
--
ALTER TABLE `accounts`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `auth_admin`
--
ALTER TABLE `auth_admin`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `accounts`
--
ALTER TABLE `accounts`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=17;
--
-- AUTO_INCREMENT for table `auth_admin`
--
ALTER TABLE `auth_admin`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
First look at the project structure
php-app/
┣ admin/
┃ ┣ assets/
┃ ┃ ┗ img/
┃ ┃ ┗ body-bg.jpg
┃ ┣ all_users.php
┃ ┣ create_user.php
┃ ┣ footer.php
┃ ┣ header.php
┃ ┣ home.php
┃ ┣ index.php
┃ ┣ logout.php
┃ ┣ proccess_new_user.php
┃ ┣ process_login.php
┃ ┗ style.css
┣ assets/
┃ ┗ img/
┃ ┗ body-bg.jpg
┣ comman/
┃ ┗ authenticate.php
┣ authenticate.php
┣ home.php
┣ index.php
┣ logout.php
┣ phplogin.sql
┣ process_login.php
┗ style.css
Admin Login
Admin can login and new user and send username and password to anyone so they can login to user
see the project structure all, I am doing inside admin directory
header.php
<?php
// We need to use sessions, so you should always start sessions using the below code.
// If the user is not logged in redirect to the login page...
if (!isset($_SESSION['loggedin'])) {
header('Location: index.php');
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home Page</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
<link href="https://cdn.datatables.net/1.10.24/css/jquery.dataTables.min.css" rel="stylesheet">
<style>
body{
margin: 0;
padding: 0;
}
.navtop {
background-color: #1e2833;
height: 60px;
width: 100%;
border: 0;
}
.navtop div {
display: flex;
margin: 0 auto;
width: 1000px;
height: 100%;
}
.navtop div h1, .navtop div a {
display: inline-flex;
align-items: center;
}
.navtop div h1 {
flex: 1;
font-size: 24px;
padding: 0;
margin: 0;
color: #eaebed;
font-weight: normal;
}
.navtop div a {
padding: 0 20px;
text-decoration: none;
color: #c1c4c8;
font-weight: bold;
}
.navtop div a i {
padding: 2px 8px 0 0;
}
.navtop div a:hover {
color: #eaebed;
}
body.loggedin {
background-color: #f3f4f7;
}
.content {
width: 1000px;
margin: 0 auto;
}
.content h2 {
margin: 0;
padding: 25px 0;
font-size: 22px;
border-bottom: 1px solid #e0e0e3;
color: #4a536e;
}
.content > p, .content > div {
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.1);
margin: 25px 0;
padding: 25px;
background-color: #fff;
}
.content > p table td, .content > div table td {
padding: 5px;
}
.content > p table td:first-child, .content > div table td:first-child {
font-weight: bold;
color: #4a536e;
padding-right: 15px;
}
.content > div p {
padding: 5px;
margin: 0 0 10px 0;
}
.error{
color: red!important;
}
</style>
</head>
<body class="loggedin">
<nav class="navtop">
<div>
<h1>Website Title</h1>
<a href="all_users.php"><i class="fas fa-user-circle"></i>All Users</a>
<a href="create_user.php"><i class="fas fa-user-circle"></i>Create User</a>
<a href="logout.php"><i class="fas fa-sign-out-alt"></i>Logout</a>
</div>
</nav>
<div class="content">
footer.php
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.10.24/js/jquery.dataTables.min.js"></script>
<script>
$('#table-users').dataTable();
</script>
</body>
</html>
index.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Untitled</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="login-dark">
<form method="post" action="process_login.php">
<h2 class="sr-only">Login Form</h2>
<div class="illustration"><i class="icon ion-ios-locked-outline"></i></div>
<div class="form-group"><input class="form-control" type="text" name="username" placeholder="Email"></div>
<div class="form-group"><input class="form-control" type="password" name="password" placeholder="Password"></div>
<div class="form-group"><button class="btn btn-primary btn-block" type="submit">Log In</button></div><a href="#" class="forgot">Forgot your email or password?</a></form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>
home.php
<?php include '../comman/authenticate.php'; ?>
<?php include_once './header.php'; ?>
<h2>Home Page</h2>
<p>Welcome back, <?= $_SESSION['name'] ?>!</p>
<?php include_once './footer.php'; ?>
process_login.php
<?php
include '../comman/authenticate.php';
// Now we check if the data from the login form was submitted, isset() will check if the data exists.
if (!isset($_POST['username'], $_POST['password'])) {
// Could not get the data that should have been sent.
exit('Please fill both the username and password fields!');
}
// Prepare our SQL, preparing the SQL statement will prevent SQL injection.
if ($stmt = $con->prepare('SELECT id, password FROM auth_admin WHERE username = ?')) {
// Bind parameters (s = string, i = int, b = blob, etc), in our case the username is a string so we use "s"
$stmt->bind_param('s', $_POST['username']);
$stmt->execute();
// Store the result so we can check if the account exists in the database.
$stmt->store_result();
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $password);
$stmt->fetch();
// Account exists, now we verify the password.
// Note: remember to use password_hash in your registration file to store the hashed passwords.
if (password_verify($_POST['password'], $password)) {
// Verification success! User has logged-in!
// Create sessions, so we know the user is logged in, they basically act like cookies but remember the data on the server.
session_regenerate_id();
$_SESSION['loggedin'] = TRUE;
$_SESSION['name'] = $_POST['username'];
$_SESSION['id'] = $id;
header('Location: home.php');
} else {
// Incorrect password
echo 'Incorrect username and/or password!';
}
} else {
// Incorrect username
echo 'Incorrect username and/or password!';
}
$stmt->close();
}
logout.php
<?php
session_start();
session_destroy();
// Redirect to the login page:
header('Location: index.php');
?>
create_user.php
<?php include '../comman/authenticate.php'; ?>
<?php include_once './header.php'; ?>
<h2>Add New user</h2>
<form accept-charset="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<?php
$nameErr = $emailErr = $passwordErr = "";
$username = $email = $password = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["username"])) {
$nameErr = "Name is required";
} else {
$username = test_input($_POST["username"]);
}
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
}
}
if (empty($_POST["password"])) {
$passwordErr = "Password is required";
} else {
$password = test_input($_POST["password"]);
}
$sql = "SELECT * FROM accounts WHERE username = '$username'";
$email_sql = "SELECT * FROM accounts WHERE email = '$email'";
$result = $con->query($sql);
$check_email_result = $con->query($email_sql);
if ($result->num_rows > 0) {
$nameErr = "Username already exists";
} else if ($check_email_result->num_rows > 0) {
$emailErr = "Email already exists";
} else {
//insert data;
$ency_pass = password_hash($password, PASSWORD_DEFAULT);
$sql = "INSERT INTO accounts (username, password, email,non_enc_pass) VALUES ('$username', '$ency_pass', '$email','$password')";
if ($con->query($sql) === TRUE) {
?>
<div class="alert alert-primary" role="alert">
<?php echo "New user created successfully";?>
</div>
<?php
} else {
echo "Error: <br>" . $con->error;
}
}
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<div class="form-group">
<label for="username">Username*</label>
<input type="text" class="form-control" name="username" placeholder="Username" value="<?php echo $username; ?>">
<small class = "error form-text text-muted"> <?php echo $nameErr; ?></small >
</div>
<div class="form-group">
<label for="email">Email address*</label>
<input type="email" class="form-control" name="email" placeholder="Enter email" value="<?php echo $email; ?>">
<small class = "error form-text text-muted"> <?php echo $emailErr; ?></small >
</div>
<div class="form-group">
<label for="password">Password*</label>
<input type="password" class="form-control" name="password" placeholder="Password">
<small class = "error form-text text-muted"> <?php echo $passwordErr; ?></small >
</div>
<button type="submit" class="btn btn-dark">Create Now</button>
</form>
<?php include_once './footer.php'; ?>
all_users.php
<?php include '../comman/authenticate.php'; ?>
<?php include_once './header.php'; ?>
<h2>All Users</h2>
<table class="table" id="table-users">
<thead class="thead-dark">
<tr>
<th scope="col">Username</th>
<th scope="col">Email</th>
<th scope="col">Password</th>
</tr>
</thead>
<tbody>
<?php
$sql = "SELECT * FROM accounts";
$result = $con->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while ($row = $result->fetch_assoc()) {
?>
<tr>
<td><?php echo $row['username']; ?></td>
<td><?php echo $row['email']; ?></td>
<td><?php echo $row['non_enc_pass']; ?></td>
</tr>
<?php
}
} else {
echo "0 results";
}
?>
</tbody>
</table>
<?php include_once './footer.php'; ?>
style.css
body{
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
background:#475d62 url(assets/img/body-bg.jpg);
}
.login-dark {
}
.login-dark form {
max-width:320px;
width:90%;
background-color:#1e2833;
padding:40px;
border-radius:4px;
transform:translate(-50%, -50%);
position:absolute;
top:50%;
left:50%;
color:#fff;
box-shadow:3px 3px 4px rgba(0,0,0,0.2);
}
.login-dark .illustration {
text-align:center;
padding:15px 0 20px;
font-size:100px;
color:#2980ef;
}
.login-dark form .form-control {
background:none;
border:none;
border-bottom:1px solid #434a52;
border-radius:0;
box-shadow:none;
outline:none;
color:inherit;
}
.login-dark form .btn-primary {
background:#214a80;
border:none;
border-radius:4px;
padding:11px;
box-shadow:none;
margin-top:26px;
text-shadow:none;
outline:none;
}
.login-dark form .btn-primary:hover, .login-dark form .btn-primary:active {
background:#214a80;
outline:none;
}
.login-dark form .forgot {
display:block;
text-align:center;
font-size:12px;
color:#6f7a85;
opacity:0.9;
text-decoration:none;
}
.login-dark form .forgot:hover, .login-dark form .forgot:active {
opacity:1;
text-decoration:none;
}
.login-dark form .btn-primary:active {
transform:translateY(1px);
}
Private User Login
If admin username and password send then you can login.
comman/authenticate.php
<?php
session_start();
// Change this to your connection info.
$DATABASE_HOST = 'localhost';
$DATABASE_USER = 'root';
$DATABASE_PASS = '';
$DATABASE_NAME = 'phplogin';
// Try and connect using the info above.
$con = new mysqli($DATABASE_HOST, $DATABASE_USER, $DATABASE_PASS, $DATABASE_NAME);
if (mysqli_connect_errno()) {
// If there is an error with the connection, stop the script and display the error.
exit('Failed to connect to MySQL: ' . mysqli_connect_error());
}
index.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Untitled</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="login-dark">
<form method="post" action="process_login.php">
<h2 class="sr-only">Login Form</h2>
<div class="illustration"><i class="icon ion-ios-locked-outline"></i></div>
<div class="form-group"><input class="form-control" type="text" name="username" placeholder="Username"></div>
<div class="form-group"><input class="form-control" type="password" name="password" placeholder="Password"></div>
<div class="form-group"><button class="btn btn-primary btn-block" type="submit">Log In</button></div><a href="#" class="forgot">Forgot your email or password?</a></form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>
home.php
<?php
// We need to use sessions, so you should always start sessions using the below code.
session_start();
// If the user is not logged in redirect to the login page...
if (!isset($_SESSION['loggedin'])) {
header('Location: index.php');
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Home Page</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
<style>
body{
margin: 0;
padding: 0;
}
.navtop {
background-color: #1e2833;
height: 60px;
width: 100%;
border: 0;
}
.navtop div {
display: flex;
margin: 0 auto;
width: 1000px;
height: 100%;
}
.navtop div h1, .navtop div a {
display: inline-flex;
align-items: center;
}
.navtop div h1 {
flex: 1;
font-size: 24px;
padding: 0;
margin: 0;
color: #eaebed;
font-weight: normal;
}
.navtop div a {
padding: 0 20px;
text-decoration: none;
color: #c1c4c8;
font-weight: bold;
}
.navtop div a i {
padding: 2px 8px 0 0;
}
.navtop div a:hover {
color: #eaebed;
}
body.loggedin {
background-color: #f3f4f7;
}
.content {
width: 1000px;
margin: 0 auto;
}
.content h2 {
margin: 0;
padding: 25px 0;
font-size: 22px;
border-bottom: 1px solid #e0e0e3;
color: #4a536e;
}
.content > p, .content > div {
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.1);
margin: 25px 0;
padding: 25px;
background-color: #fff;
}
.content > p table td, .content > div table td {
padding: 5px;
}
.content > p table td:first-child, .content > div table td:first-child {
font-weight: bold;
color: #4a536e;
padding-right: 15px;
}
.content > div p {
padding: 5px;
margin: 0 0 10px 0;
}
</style>
</head>
<body class="loggedin">
<nav class="navtop">
<div>
<h1>Website Title</h1>
<a href="logout.php"><i class="fas fa-sign-out-alt"></i>Logout</a>
</div>
</nav>
<div class="content">
<h2>Home Page</h2>
<p>Welcome back, <?= $_SESSION['name'] ?>!</p>
</div>
</body>
</html>
process_login.php
<?php
include './authenticate.php';
// Now we check if the data from the login form was submitted, isset() will check if the data exists.
if (!isset($_POST['username'], $_POST['password'])) {
// Could not get the data that should have been sent.
exit('Please fill both the username and password fields!');
}
// Prepare our SQL, preparing the SQL statement will prevent SQL injection.
if ($stmt = $con->prepare('SELECT id, password FROM accounts WHERE username = ?')) {
// Bind parameters (s = string, i = int, b = blob, etc), in our case the username is a string so we use "s"
$stmt->bind_param('s', $_POST['username']);
$stmt->execute();
// Store the result so we can check if the account exists in the database.
$stmt->store_result();
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $password);
$stmt->fetch();
// Account exists, now we verify the password.
// Note: remember to use password_hash in your registration file to store the hashed passwords.
if (password_verify($_POST['password'], $password)) {
// Verification success! User has logged-in!
// Create sessions, so we know the user is logged in, they basically act like cookies but remember the data on the server.
session_regenerate_id();
$_SESSION['loggedin'] = TRUE;
$_SESSION['name'] = $_POST['username'];
$_SESSION['id'] = $id;
header('Location: home.php');
} else {
// Incorrect password
echo 'Incorrect username and/or password!';
}
} else {
// Incorrect username
echo 'Incorrect username and/or password!';
}
$stmt->close();
}
logout.php
<?php
session_start();
session_destroy();
// Redirect to the login page:
header('Location: index.php');
?>
style.css
body{
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
background:#475d62 url(assets/img/body-bg.jpg);
}
.login-dark {
}
.login-dark form {
max-width:320px;
width:90%;
background-color:#1e2833;
padding:40px;
border-radius:4px;
transform:translate(-50%, -50%);
position:absolute;
top:50%;
left:50%;
color:#fff;
box-shadow:3px 3px 4px rgba(0,0,0,0.2);
}
.login-dark .illustration {
text-align:center;
padding:15px 0 20px;
font-size:100px;
color:#2980ef;
}
.login-dark form .form-control {
background:none;
border:none;
border-bottom:1px solid #434a52;
border-radius:0;
box-shadow:none;
outline:none;
color:inherit;
}
.login-dark form .btn-primary {
background:#214a80;
border:none;
border-radius:4px;
padding:11px;
box-shadow:none;
margin-top:26px;
text-shadow:none;
outline:none;
}
.login-dark form .btn-primary:hover, .login-dark form .btn-primary:active {
background:#214a80;
outline:none;
}
.login-dark form .forgot {
display:block;
text-align:center;
font-size:12px;
color:#6f7a85;
opacity:0.9;
text-decoration:none;
}
.login-dark form .forgot:hover, .login-dark form .forgot:active {
opacity:1;
text-decoration:none;
}
.login-dark form .btn-primary:active {
transform:translateY(1px);
}
Note: If above example not work you can download zip file of source code.
Thanks. May this example help you