When developing a PHP-based application where multiple users need to log in and access files securely, ensuring both proper authentication and authorization is critical. This guide walks through the process of creating a multi-user login system using PHP that protects files, with a focus on security measures like password hashing, secure session management, and user roles.
Prerequisites
Before diving into the code, ensure that your environment has the following:
- Web Server: Apache or Nginx
- PHP: Version 7.4 or later
- MySQL or MariaDB: For storing user data
- PHP Extensions:
mysqli,session,password_hash()
Step 1: Database Setup
First, set up a database to store user details such as usernames, passwords, and roles (for authorization). Use phpMyAdmin or another MySQL tool to create the following database and table structure:
CREATE DATABASE secure_login;
USE secure_login;
CREATE TABLE users (
id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role ENUM('user', 'admin') NOT NULL DEFAULT 'user'
);
Step 2: Secure User Registration (Optional)
While you could manually add users to the database, it’s good practice to provide a registration mechanism (admin-only, if needed). Ensure that passwords are securely hashed using PHP’s password_hash() function.
Here’s an example of a registration script (register.php):
<?php
require 'config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$role = $_POST['role']; // Assigning role, 'user' or 'admin'
// Hash the password
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
// Insert into the database
$stmt = $conn->prepare("INSERT INTO users (username, password, role) VALUES (?, ?, ?)");
$stmt->bind_param('sss', $username, $hashedPassword, $role);
if ($stmt->execute()) {
echo "User registered successfully.";
} else {
echo "Registration failed: " . $conn->error;
}
$stmt->close();
}
?>
<form method="post" action="register.php">
Username: <input type="text" name="username" required><br>
Password: <input type="password" name="password" required><br>
Role:
<select name="role">
<option value="user">User</option>
<option value="admin">Admin</option>
</select><br>
<input type="submit" value="Register">
</form>
Step 3: User Login Authentication
To secure file access, users need to authenticate themselves. In this example, passwords will be verified using password_verify() (to compare the stored hash with the provided password).
Create a login.php script:
<?php
session_start();
require 'config.php'; // Database connection
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
$stmt = $conn->prepare("SELECT id, password, role FROM users WHERE username = ?");
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
$stmt->bind_result($id, $hashedPassword, $role);
$stmt->fetch();
if (password_verify($password, $hashedPassword)) {
$_SESSION['user_id'] = $id;
$_SESSION['username'] = $username;
$_SESSION['role'] = $role;
header('Location: dashboard.php');
exit;
} else {
echo "Invalid credentials.";
}
} else {
echo "No user found.";
}
$stmt->close();
}
?>
<form method="post" action="login.php">
Username: <input type="text" name="username" required><br>
Password: <input type="password" name="password" required><br>
<input type="submit" value="Login">
</form>
Step 4: Dashboard and Role-Based Access Control
Once users are authenticated, they should be redirected to a secure dashboard (dashboard.php). To enforce different access levels, implement role-based access control (RBAC) by checking the user’s role.
Example dashboard.php:
<?php
session_start();
// Redirect if not logged in
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
// Show content based on role
echo "Welcome, " . $_SESSION['username'] . "<br>";
if ($_SESSION['role'] === 'admin') {
echo "You have administrative privileges.<br>";
echo '<a href="admin_page.php">Go to admin page</a>';
} else {
echo "You have user access.<br>";
}
echo '<a href="logout.php">Logout</a>';
?>
Step 5: Secure File Access with Authorization
To protect specific files, ensure that users can only access them after logging in. For more sensitive files (e.g., admin-only files), add role verification.
Example for a protected file (admin_page.php):
<?php
session_start();
// Check if the user is logged in and is an admin
if (!isset($_SESSION['user_id']) || $_SESSION['role'] !== 'admin') {
header('Location: login.php');
exit;
}
echo "Welcome to the admin area, " . $_SESSION['username'] . "!";
?>
This ensures that only users with the admin role can access this page.
Step 6: Secure Sessions
Sessions in PHP manage user state, but they need to be secured to prevent hijacking or fixation attacks. Use the following strategies:
- Use HTTPS: Ensure your site runs over HTTPS to encrypt session data during transmission.
- Regenerate session IDs: Call
session_regenerate_id()after login to prevent fixation attacks. - Set proper session options: Use secure cookies and set the
httponlyflag.
Here’s how to start a secure session:
session_start([
'cookie_lifetime' => 86400,
'cookie_secure' => true, // Requires HTTPS
'cookie_httponly' => true,
'use_strict_mode' => true
]);
// Regenerate session ID after login for security
session_regenerate_id(true);
Step 7: Logging Out Securely
Ensure that when a user logs out, their session is properly destroyed:
<?php
session_start();
// Unset all session variables
$_SESSION = [];
// Destroy the session
session_destroy();
// Redirect to login page
header('Location: login.php');
exit;
?>
Step 8: File Upload and Access Security
For systems allowing file uploads, ensure that only authenticated users can upload and access files. To avoid unauthorized access to sensitive files, store them outside the web root, and serve them through a PHP script that checks the user’s authentication.
File upload (upload.php):
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
die("You must be logged in to upload files.");
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$uploadDir = '/var/www/secure_files/'; // Outside web root
$uploadFile = $uploadDir . basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadFile)) {
echo "File successfully uploaded.";
} else {
echo "File upload failed.";
}
}
?>
<form method="post" enctype="multipart/form-data">
<input type="file" name="file" required>
<input type="submit" value="Upload">
</form>
File Access Script (file_access.php):
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
die("Unauthorized access.");
}
$file = '/var/www/secure_files/' . basename($_GET['file']);
if (file_exists($file)) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($file));
readfile($file);
exit;
} else {
echo "File not found.";
}
?>
Step 9: Final Security Measures
- Password Hashing: Always use PHP’s
password_hash()andpassword_verify()for secure password storage. - Prepared Statements: Use prepared statements (
$stmt->bind_param()) for all database interactions to prevent SQL injection. - Input Sanitization: Use functions like
htmlspecialchars()to sanitize user input and prevent XSS (Cross-Site Scripting) attacks. - Session Security: Implement proper session handling, use
session_regenerate_id(), and enforce HTTPS for secure transmission.
By following this guide, you’ve created a secure, multi-user PHP login system that protects files based on user authentication and role-based access control. The key security aspects such as password hashing, session management, and role-based restrictions help ensure that only authorized users can access sensitive files and areas of your application. Always stay updated on the latest PHP security practices to keep your system robust against new threats.