Sessions
intermediatePart of PHP Web Features
Theory
HTTP is a stateless protocol — each request to a server is independent and unaware of previous requests. Sessions and cookies provide state management, allowing you to track users across multiple page requests.
What are Sessions?
A session is a way to store user-specific data on the server between page requests. Each session is identified by a unique session ID, which is typically stored in a cookie on the client.
When a user visits your site:
- PHP creates a unique session ID
- PHP stores this ID in a cookie (
PHPSESSID) on the user's browser - Session data is stored on the server (usually in files or a database)
- On subsequent requests, the browser sends the session ID cookie
- PHP loads the session data using the ID
Browser Server
│ │
│── First visit ──────────────→ │
│ ├── Creates session, generates ID
│← Set-Cookie: PHPSESSID=abc123 │
│ │
│── Request (with cookie) ────→ │
│ ├── Loads session data by ID
│← Response ─────────────────── │
session_start()
Every page that uses sessions must call session_start() before any output:
<?php
// Must be called before ANY HTML output
session_start();
// Now you can access and set session variables
?>
<!DOCTYPE html>
<html>
...If a session doesn't exist, session_start() creates one. If it does, it resumes the existing session.
$_SESSION
Session data is stored in the $_SESSION superglobal array:
<?php
session_start();
// Set session variables
$_SESSION['user_id'] = 42;
$_SESSION['username'] = 'alice';
$_SESSION['role'] = 'admin';
$_SESSION['login_time'] = time();
// Access session variables
echo 'Welcome back, ' . $_SESSION['username'];
// Check if a session variable exists
if (isset($_SESSION['user_id'])) {
// User is logged in
}
// Remove a specific session variable
unset($_SESSION['cart_item']);
// Destroy all session data
session_destroy();
?>Login/Logout Flow
Login:
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = $_POST['username'];
$password = $_POST['password'];
// Verify credentials (in real app, check database)
if ($username === 'admin' && $password === 'secret') {
// Regenerate session ID to prevent session fixation
session_regenerate_id(true);
$_SESSION['user_id'] = 1;
$_SESSION['username'] = $username;
$_SESSION['role'] = 'admin';
header('Location: dashboard.php');
exit;
} else {
$error = 'Invalid credentials';
}
}
?>Protected page:
<?php
session_start();
// Check if user is logged in
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
?>
<h1>Welcome, <?= htmlspecialchars($_SESSION['username']) ?>!</h1>Logout:
<?php
session_start();
// Clear all session variables
$_SESSION = [];
// Delete session cookie
if (ini_get('session.use_cookies')) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params['path'], $params['domain'],
$params['secure'], $params['httponly']
);
}
// Destroy the session
session_destroy();
header('Location: login.php');
exit;
?>Cookies
Cookies are small pieces of data stored on the client's browser. Unlike sessions (which store data on the server), cookies store data directly on the user's computer.
setcookie() must be called before any HTML output:
<?php
// Set a cookie that expires in 7 days
setcookie('theme', 'dark', time() + 7 * 24 * 60 * 60, '/');
// Set a cookie with additional security parameters
setcookie('preferences', json_encode(['lang' => 'en', 'font' => 'large']),
time() + 30 * 24 * 60 * 60, // 30 days
'/', // Path (available across entire site)
'example.com', // Domain
true, // Secure (HTTPS only)
true // HttpOnly (not accessible by JavaScript)
);
// Read a cookie
if (isset($_COOKIE['theme'])) {
$theme = $_COOKIE['theme'];
}
// Delete a cookie (set expiration in the past)
setcookie('theme', '', time() - 3600, '/');
?>Session Security
Session Fixation Prevention:
<?php
session_start();
// Always regenerate session ID after login
session_regenerate_id(true);
// Also regenerate on privilege changes
if ($user->isAdmin()) {
session_regenerate_id(true);
}
?>Other security measures:
<?php
// Set session cookie parameters before session_start()
session_set_cookie_params([
'lifetime' => 0, // Until browser closes
'path' => '/',
'domain' => '',
'secure' => true, // HTTPS only
'httponly' => true, // Not accessible by JavaScript
'samesite' => 'Strict', // CSRF protection
]);
session_start();
// Set a session timeout (30 minutes of inactivity)
if (isset($_SESSION['last_activity']) &&
(time() - $_SESSION['last_activity'] > 1800)) {
session_unset();
session_destroy();
header('Location: login.php?timeout=1');
exit;
}
$_SESSION['last_activity'] = time();
// Regenerate session ID periodically (every 5 minutes)
if (!isset($_SESSION['last_regeneration'])) {
$_SESSION['last_regeneration'] = time();
} elseif (time() - $_SESSION['last_regeneration'] > 300) {
session_regenerate_id(true);
$_SESSION['last_regeneration'] = time();
}
?>Key security headers for session pages:
<?php
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: strict-origin-when-cross-origin');
?>Always call session_start() at the very top of your PHP files, before any HTML or whitespace output. Even a single space before <?php will cause a 'headers already sent' error when you try to set cookies or start sessions.
Practical Examples
Use session_regenerate_id(true) after login to prevent session fixation attacks. The true parameter deletes the old session file.
Exercises
Visitor Counter with Sessions
Create a PHP script that uses a session variable to track how many times the user has visited the page during their session. Display a different message for first-time and returning visitors.
Expected Output:
First visit: 'Welcome! This is your first visit.' Subsequent visits: 'Welcome back! You've visited X times.'User Preferences with Cookies
Create a PHP page that allows users to set their preferences (theme: light/dark, font size: small/medium/large, language) using cookies. The preferences should persist across visits for 30 days.
Expected Output:
Preferences saved in a cookie and applied on page load. Dark theme shows dark background with white text. Preferences persist across browser sessions.Build a Complete Auth System
Create a complete login/logout/register system using sessions. Include: registration with validation, login with remember-me cookie, protected pages, session timeout after 15 minutes of inactivity.
Expected Output:
A complete auth system with registration, login (with remember-me using a separate cookie), password-protected pages, and automatic logout after 15 minutes of inactivity.Mini Quiz
Mini Quiz
Mini Project
Mini Project: Admin Panel with Role-Based Access
Create an admin panel with user authentication, role-based access control (admin, editor, viewer), session management, and activity logging.
Requirements:
Bonus Challenge
Add a 'remember me' feature using a persistent cookie with a hashed token. Add brute-force protection (lock account after 5 failed login attempts).