Session 4.2 – PHP Sessions
Module 4: PHP Filters and Handlers | Duration: 1 hr
Learning Objectives
By the end of this session, students will be able to:
- Understand what PHP sessions are and how they differ from cookies
- Start and manage PHP sessions using session_start()
- Store and retrieve data in session variables
- Properly destroy sessions and clean up session data
- Implement secure session practices to prevent hijacking and fixation
- Build complete authentication systems using sessions
Introduction to PHP Sessions
A session is a way to preserve data across subsequent page requests. Unlike cookies which are stored on the client's browser, session data is stored on the server, making it more secure for sensitive information.
Key Insight
Sessions allow you to store user information on the server for later use across multiple pages. The server creates a unique session ID for each visitor, which is typically stored as a cookie on the client side or passed through URLs.
How Sessions Work
- When a session is started, PHP generates a unique Session ID (PHPSESSID)
- The Session ID is sent to the client (usually as a cookie)
- Session data is stored on the server with the Session ID as the key
- On subsequent requests, the client sends the Session ID back to the server
- PHP retrieves the session data using the Session ID
Starting and Managing Sessions
To use sessions in PHP, you must first start a session using the session_start() function. This must be called before any output is sent to the browser.
Basic Session Start:
<?php
// Start a new session or resume existing session
session_start();
echo "Session started successfully!";
echo "<br>Session ID: " . session_id();
?>
Important Note
Like setcookie(), the session_start() function must be called before any HTML output, whitespace, or echo statements. Otherwise, you'll receive a "headers already sent" error.
Session Configuration:
<?php
// Configure session settings before starting
ini_set('session.cookie_lifetime', 3600); // 1 hour
ini_set('session.cookie_secure', 1); // HTTPS only
ini_set('session.cookie_httponly', 1); // No JavaScript access
ini_set('session.use_strict_mode', 1); // Prevent session fixation
session_start();
?>
Session Status Check:
<?php
// Check if session is already started
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Alternative check
if (!isset($_SESSION)) {
session_start();
}
echo "Session is active!";
?>
Storing Data in Sessions
Session data is stored in the $_SESSION superglobal array. You can store any type of PHP data in sessions.
Storing Different Data Types:
<?php
session_start();
// Store string
$_SESSION["username"] = "JohnDoe";
// Store integer
$_SESSION["user_id"] = 12345;
// Store array
$_SESSION["user_data"] = [
"name" => "John Doe",
"email" => "john@example.com",
"role" => "admin"
];
// Store object
class User {
public $name;
public $email;
public function __construct($name, $email) {
$this->name = $name;
$this->email = $email;
}
}
$_SESSION["user_object"] = new User("John", "john@example.com");
// Store boolean
$_SESSION["is_logged_in"] = true;
echo "Data stored in session successfully!";
?>
Session Counter Example:
<?php
session_start();
// Initialize counter if it doesn't exist
if (!isset($_SESSION["page_views"])) {
$_SESSION["page_views"] = 0;
}
// Increment counter
$_SESSION["page_views"]++;
echo "You have viewed this page " . $_SESSION["page_views"] . " times.";
?>
Retrieving Session Data
Accessing session data is straightforward using the $_SESSION array. Always check if a session variable exists before using it.
Safe Data Retrieval:
<?php
session_start();
// Check if session variable exists
if (isset($_SESSION["username"])) {
echo "Welcome back, " . $_SESSION["username"] . "!";
} else {
echo "Please log in.";
}
// Using default values
$username = $_SESSION["username"] ?? "Guest";
echo "Hello, " . $username;
// Using isset with multiple variables
if (isset($_SESSION["user_id"], $_SESSION["username"])) {
echo "User ID: " . $_SESSION["user_id"];
echo "<br>Username: " . $_SESSION["username"];
}
?>
Retrieving Complex Data:
<?php
session_start();
// Retrieve array data
if (isset($_SESSION["user_data"])) {
$userData = $_SESSION["user_data"];
echo "Name: " . $userData["name"] . "<br>";
echo "Email: " . $userData["email"] . "<br>";
echo "Role: " . $userData["role"];
}
// Retrieve object data
if (isset($_SESSION["user_object"])) {
$user = $_SESSION["user_object"];
echo "User: " . $user->name . " (" . $user->email . ")";
}
?>
Display All Session Data:
<?php
session_start();
echo "<h3>Current Session Data:</h3>";
echo "<pre>";
print_r($_SESSION);
echo "</pre>";
// Or use var_dump for more details
echo "<h3>Detailed Session Data:</h3>";
echo "<pre>";
var_dump($_SESSION);
echo "</pre>";
?>
Destroying Sessions and Session Data
Properly destroying sessions is crucial for security, especially for logout functionality.
Removing Individual Session Variables:
<?php
session_start();
// Remove a specific session variable
unset($_SESSION["username"]);
// Remove multiple variables
unset($_SESSION["user_id"], $_SESSION["email"]);
echo "Session variables removed.";
?>
Complete Session Destruction:
<?php
session_start();
// Step 1: Unset all session variables
$_SESSION = array();
// Step 2: Delete the session cookie
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time() - 3600, '/');
}
// Step 3: Destroy the session
session_destroy();
echo "Session completely destroyed!";
?>
Proper Logout Function:
<?php
// logout.php
function logout() {
// Start session if not already started
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Unset all session variables
$_SESSION = array();
// 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 session
session_destroy();
// Redirect to login page
header("Location: login.php");
exit();
}
// Call logout function
logout();
?>
Session Regeneration (Prevent Fixation):
<?php
session_start();
// Regenerate session ID to prevent session fixation
session_regenerate_id(true);
echo "Session ID has been regenerated.";
echo "<br>New Session ID: " . session_id();
?>
Session Security Best Practices
Implementing proper security measures is essential to protect against session hijacking, fixation, and other attacks.
1. Secure Session Configuration:
<?php
// config/session_config.php
ini_set('session.cookie_httponly', 1); // Prevent JavaScript access
ini_set('session.use_only_cookies', 1); // Force cookies only
ini_set('session.cookie_secure', 1); // HTTPS only
ini_set('session.cookie_samesite', 'Strict'); // CSRF protection
ini_set('session.use_strict_mode', 1); // Reject uninitialized session IDs
session_start();
?>
2. Session Timeout Implementation:
<?php
session_start();
// Set timeout duration (30 minutes)
$timeout_duration = 1800;
// Check if session has expired
if (isset($_SESSION['last_activity'])) {
$elapsed_time = time() - $_SESSION['last_activity'];
if ($elapsed_time > $timeout_duration) {
// Session expired
session_unset();
session_destroy();
header("Location: login.php?timeout=1");
exit();
}
}
// Update last activity timestamp
$_SESSION['last_activity'] = time();
?>
3. Session Hijacking Prevention:
<?php
session_start();
// Store user agent and IP address
if (!isset($_SESSION['user_agent'])) {
$_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
}
if (!isset($_SESSION['ip_address'])) {
$_SESSION['ip_address'] = $_SERVER['REMOTE_ADDR'];
}
// Verify session on each request
if ($_SESSION['user_agent'] !== $_SERVER['HTTP_USER_AGENT'] ||
$_SESSION['ip_address'] !== $_SERVER['REMOTE_ADDR']) {
// Possible session hijacking detected
session_unset();
session_destroy();
die("Security violation detected!");
}
?>
4. Regenerate Session ID After Login:
<?php
// login_process.php
session_start();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = $_POST["username"];
$password = $_POST["password"];
// Verify credentials (simplified)
if (verify_credentials($username, $password)) {
// Regenerate session ID to prevent fixation
session_regenerate_id(true);
// Set session variables
$_SESSION['user_id'] = get_user_id($username);
$_SESSION['username'] = $username;
$_SESSION['logged_in'] = true;
$_SESSION['login_time'] = time();
// Redirect to dashboard
header("Location: dashboard.php");
exit();
}
}
function verify_credentials($username, $password) {
// Database verification logic here
return true;
}
function get_user_id($username) {
// Retrieve user ID from database
return 12345;
}
?>
Security Checklist
- Always use HTTPS in production
- Set HttpOnly and Secure flags on session cookies
- Regenerate session ID after login
- Implement session timeouts
- Validate user agent and IP address
- Use strong session ID generation
- Store sessions securely on the server
- Never expose session IDs in URLs
Practical Examples
Example 1: Complete Login System
<?php
// login.php
session_start();
// Redirect if already logged in
if (isset($_SESSION["logged_in"]) && $_SESSION["logged_in"] === true) {
header("Location: dashboard.php");
exit();
}
$error = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = trim($_POST["username"]);
$password = $_POST["password"];
// Validate credentials (simplified)
if ($username === "admin" && $password === "password123") {
// Regenerate session ID
session_regenerate_id(true);
// Set session variables
$_SESSION["logged_in"] = true;
$_SESSION["username"] = $username;
$_SESSION["user_id"] = 1;
$_SESSION["login_time"] = time();
header("Location: dashboard.php");
exit();
} else {
$error = "Invalid username or password";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<?php if ($error): ?>
<p style="color: red;"><?php echo $error; ?></p>
<?php endif; ?>
<form method="POST" action="">
<input type="text" name="username" placeholder="Username" required><br>
<input type="password" name="password" placeholder="Password" required><br>
<button type="submit">Login</button>
</form>
</body>
</html>
Example 2: Protected Dashboard
<?php
// dashboard.php
session_start();
// Check if user is logged in
if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
header("Location: login.php");
exit();
}
// Calculate session duration
$session_duration = time() - $_SESSION["login_time"];
$minutes = floor($session_duration / 60);
?>
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<h1>Welcome, <?php echo htmlspecialchars($_SESSION["username"]); ?>!</h1>
<p>User ID: <?php echo $_SESSION["user_id"]; ?></p>
<p>Logged in for: <?php echo $minutes; ?> minutes</p>
<p><a href="logout.php">Logout</a></p>
</body>
</html>
Example 3: Shopping Cart with Sessions
<?php
// cart.php
session_start();
// Initialize cart if it doesn't exist
if (!isset($_SESSION["cart"])) {
$_SESSION["cart"] = [];
}
// Add item to cart
if (isset($_POST["add_to_cart"])) {
$product_id = $_POST["product_id"];
$product_name = $_POST["product_name"];
$price = $_POST["price"];
// Check if product already in cart
if (isset($_SESSION["cart"][$product_id])) {
$_SESSION["cart"][$product_id]["quantity"]++;
} else {
$_SESSION["cart"][$product_id] = [
"name" => $product_name,
"price" => $price,
"quantity" => 1
];
}
}
// Remove item from cart
if (isset($_GET["remove"])) {
$product_id = $_GET["remove"];
unset($_SESSION["cart"][$product_id]);
}
// Clear entire cart
if (isset($_GET["clear"])) {
$_SESSION["cart"] = [];
}
// Calculate total
$total = 0;
foreach ($_SESSION["cart"] as $item) {
$total += $item["price"] * $item["quantity"];
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Shopping Cart</title>
</head>
<body>
<h1>Shopping Cart</h1>
<?php if (empty($_SESSION["cart"])): ?>
<p>Your cart is empty.</p>
<?php else: ?>
<table border="1">
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Subtotal</th>
<th>Action</th>
</tr>
<?php foreach ($_SESSION["cart"] as $id => $item): ?>
<tr>
<td><?php echo htmlspecialchars($item["name"]); ?></td>
<td>$<?php echo number_format($item["price"], 2); ?></td>
<td><?php echo $item["quantity"]; ?></td>
<td>$<?php echo number_format($item["price"] * $item["quantity"], 2); ?></td>
<td><a href="?remove=<?php echo $id; ?>">Remove</a></td>
</tr>
<?php endforeach; ?>
<tr>
<td colspan="3"><strong>Total:</strong></td>
<td><strong>$<?php echo number_format($total, 2); ?></strong></td>
<td></td>
</tr>
</table>
<p><a href="?clear=1">Clear Cart</a></p>
<?php endif; ?>
<h2>Add Products</h2>
<form method="POST">
<input type="hidden" name="product_id" value="1">
<input type="hidden" name="product_name" value="Laptop">
<input type="hidden" name="price" value="999.99">
<button type="submit" name="add_to_cart">Add Laptop ($999.99)</button>
</form>
<form method="POST">
<input type="hidden" name="product_id" value="2">
<input type="hidden" name="product_name" value="Mouse">
<input type="hidden" name="price" value="29.99">
<button type="submit" name="add_to_cart">Add Mouse ($29.99)</button>
</form>
</body>
</html>
Example 4: Multi-Step Form with Sessions
<?php
// step1.php
session_start();
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$_SESSION["step1"] = [
"first_name" => $_POST["first_name"],
"last_name" => $_POST["last_name"],
"email" => $_POST["email"]
];
header("Location: step2.php");
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Step 1: Personal Information</title>
</head>
<body>
<h2>Step 1 of 3: Personal Information</h2>
<form method="POST">
<input type="text" name="first_name" placeholder="First Name" required><br>
<input type="text" name="last_name" placeholder="Last Name" required><br>
<input type="email" name="email" placeholder="Email" required><br>
<button type="submit">Next</button>
</form>
</body>
</html>
<?php
// step2.php
session_start();
if (!isset($_SESSION["step1"])) {
header("Location: step1.php");
exit();
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$_SESSION["step2"] = [
"address" => $_POST["address"],
"city" => $_POST["city"],
"zip" => $_POST["zip"]
];
header("Location: step3.php");
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Step 2: Address</title>
</head>
<body>
<h2>Step 2 of 3: Address</h2>
<form method="POST">
<input type="text" name="address" placeholder="Street Address" required><br>
<input type="text" name="city" placeholder="City" required><br>
<input type="text" name="zip" placeholder="ZIP Code" required><br>
<button type="submit">Next</button>
</form>
</body>
</html>
<?php
// step3.php
session_start();
if (!isset($_SESSION["step1"]) || !isset($_SESSION["step2"])) {
header("Location: step1.php");
exit();
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Process complete form
$complete_data = array_merge(
$_SESSION["step1"],
$_SESSION["step2"],
["phone" => $_POST["phone"]]
);
// Save to database or process data
// ...
// Clear session data
unset($_SESSION["step1"]);
unset($_SESSION["step2"]);
echo "Form submitted successfully!";
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Step 3: Confirmation</title>
</head>
<body>
<h2>Step 3 of 3: Confirmation</h2>
<h3>Review Your Information:</h3>
<p>Name: <?php echo $_SESSION["step1"]["first_name"] . " " . $_SESSION["step1"]["last_name"]; ?></p>
<p>Email: <?php echo $_SESSION["step1"]["email"]; ?></p>
<p>Address: <?php echo $_SESSION["step2"]["address"]; ?></p>
<p>City: <?php echo $_SESSION["step2"]["city"]; ?></p>
<p>ZIP: <?php echo $_SESSION["step2"]["zip"]; ?></p>
<form method="POST">
<input type="tel" name="phone" placeholder="Phone Number" required><br>
<button type="submit">Submit</button>
</form>
</body>
</html>
Session Summary
Key Points
- Sessions store data on the server, making them more secure than cookies
- Use
session_start()to begin or resume a session - Store data in the
$_SESSIONsuperglobal array - Sessions persist across multiple pages until destroyed or expired
- Always implement proper session destruction on logout
- Regenerate session IDs after login to prevent fixation attacks
- Implement session timeouts and validation for security
- Use HTTPS and security flags (HttpOnly, Secure) in production
Next Session Preview
In the next session, we will explore Call-back Functions in PHP, learning how to use anonymous functions, closures, and callbacks to create more flexible and reusable code.