PHP Sessions
Also Known As
TL;DR
Explanation
PHP sessions work by: session_start() checks for a session cookie (PHPSESSID by default), creates a new session file (or entry in Redis/database) if none exists, and populates the $_SESSION superglobal from stored data. Session data is serialised to disk by default (session.save_path) or to a custom handler (Redis, Memcached, database). The session ID is sent to the browser as a cookie. Security requirements: session.cookie_httponly = true (prevents JavaScript access); session.cookie_secure = true (HTTPS only); session.cookie_samesite = 'Lax' (CSRF protection); session.use_strict_mode = true (rejects unrecognised session IDs); session_regenerate_id(true) after login (destroys old session, creates new — prevents session fixation); session_destroy() on logout (invalidates server-side data). PHP file-based sessions do not scale across multiple servers — use Redis or a database session handler for multi-server deployments.
Common Misconception
Why It Matters
Common Mistakes
- Not calling session_start() at the beginning of every page that uses sessions — $_SESSION is empty without it.
- Not regenerating the session ID after login — exposes the application to session fixation attacks.
- Using file-based sessions in a multi-server environment — sessions are not shared across servers; use Redis.
- Not calling session_destroy() on logout — invalidating the cookie without destroying the server-side data leaves the session exploitable if the cookie is obtained.
Code Examples
<?php
session_start();
// Login check — no regeneration
if (checkCredentials($_POST['user'], $_POST['pass'])) {
$_SESSION['user'] = $_POST['user'];
// No session_regenerate_id — session fixation possible
// No secure/httponly cookie settings
}
<?php
// Secure session configuration
ini_set('session.cookie_httponly', '1');
ini_set('session.cookie_secure', '1');
ini_set('session.cookie_samesite', 'Lax');
ini_set('session.use_strict_mode', '1');
session_start();
if (checkCredentials($_POST['user'], $_POST['pass'])) {
session_regenerate_id(true); // new ID, old destroyed
$_SESSION['user_id'] = getUserId($_POST['user']);
$_SESSION['logged_in'] = true;
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
header('Location: /dashboard');
exit;
}