aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Development

PHP Session and Cookie: Secure State Management

A PHP session is the most fundamental way to remember a user across pages despite HTTP being stateless. When someone logs in, adds an item to a cart, or switches their language preference, you need to know that on the next request too. Sessions and cookies work together to make this possible. In this article you'll see step by step how the two work, which settings keep them secure, and how to defend against typical attacks like session fixation.

The difference between a session and a cookie

The two are often confused, but their jobs differ. A cookie is a small piece of data stored in the browser and sent back to the server on every request. A session is a mechanism where the data lives on the server side; the browser only holds an identifier (the session ID) pointing to it. This distinction matters: sensitive data such as the user's email or permission level stays on the server, and only an unguessable ID travels to the browser.

  • Cookie: In the browser, in plain text. The user can read and change it. Suitable for non-sensitive data like language preference or theme.
  • Session: On the server. The user only holds the ID and cannot see its contents. The right choice for authentication and sensitive state.

Starting a session

A session always begins with session_start(). This call must happen before any output is sent — that is, before any echo or HTML — otherwise you get the "headers already sent" error. Once started, you read and write data through the $_SESSION superglobal array.

<?php
session_start();

// Writing data
$_SESSION['user_id'] = 42;
$_SESSION['locale']  = 'en';

// Reading data
$userId = $_SESSION['user_id'] ?? null;

By default session data is stored in a file on the server, and the session ID is sent to the browser in a cookie named PHPSESSID. So a cookie is already used behind the scenes; that's why the cookie settings protecting the session ID directly affect its security.

Secure cookie flags

A large part of session security comes from giving the session cookie the right flags. You set these with session_set_cookie_params() before the session_start() call. Three flags are critical:

<?php
session_set_cookie_params([
    'lifetime' => 0,          // ends when the browser closes
    'path'     => '/',
    'secure'   => true,       // HTTPS only
    'httponly' => true,       // JavaScript cannot access it
    'samesite' => 'Lax',      // protection against CSRF
]);

session_start();
  • Secure: The cookie is only sent over an HTTPS connection. This prevents the session ID from being stolen over plain HTTP.
  • HttpOnly: The cookie cannot be reached from JavaScript via document.cookie. Even if an XSS flaw exists, it makes stealing the session ID much harder.
  • SameSite: Controls whether the cookie is sent on requests coming from other sites. Lax is a good balance for most apps; Strict is more restrictive.

Defending against session fixation

A session fixation attack works by getting the victim to use a session ID the attacker already knows. When the victim logs in with that ID, the attacker slips into the session using the same ID. The fix is simple but critical: regenerate the session ID whenever the privilege level changes. In other words, call session_regenerate_id() the moment the user logs in.

<?php
// AFTER the password is verified
if (password_verify($password, $hash)) {
    // Invalidate the old session, generate a new ID
    session_regenerate_id(true);

    $_SESSION['user_id']   = $user['id'];
    $_SESSION['logged_in'] = true;
}

The true argument here also deletes the old session file. The same principle applies to privilege escalation, such as a normal user moving into an admin panel.

Closing a session securely

Logging out is not finished by just clearing $_SESSION. You must clean up both the data on the server and the cookie in the browser. A complete logout looks like this:

<?php
session_start();

// 1. Empty the session data
$_SESSION = [];

// 2. Delete the 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']
    );
}

// 3. Destroy the session on the server
session_destroy();

Skipping any of these three steps is a common mistake: if you only call session_destroy(), a stale cookie may remain in the browser; if you only do $_SESSION = [], the file on the server is not removed.

Using your own cookies correctly

Beyond sessions, you can use cookies directly for non-sensitive data such as a language or theme preference. From PHP 7.3 onward, setcookie() supports taking its options as an array, which lets you define modern flags like SameSite cleanly:

<?php
setcookie('theme', 'dark', [
    'expires'  => time() + 60 * 60 * 24 * 30, // 30 days
    'path'     => '/',
    'secure'   => true,
    'httponly' => false,   // if JS needs to read it
    'samesite' => 'Lax',
]);

Remember: data you write to a cookie can be changed by the user. So never base a trust decision like "is this user an admin?" on a cookie value. Authorization decisions must always rely on the server-side session.

Frequently Asked Questions

Where is session data stored?

By default, as a file in a temporary folder on the server. The session.save_path setting defines this location. In apps that scale out, it's common to switch to a Redis- or database-backed session driver so that multiple servers can see the same session.

How long does a session live?

Two settings affect this: session.gc_maxlifetime decides how long the data stays valid on the server, while the cookie's lifetime decides how long the browser keeps the session ID. If you want a real "log out after X" timeout, the most reliable way is to store the last activity time in the session and check it yourself.

Can I keep sensitive data in a cookie?

No. A cookie sits in the browser in plain text and can be read and changed by the user. Things like passwords or permission levels must stay in the server-side session; a cookie should only carry the unguessable session ID or non-sensitive preferences.

Get session management right from the start. If you want to make authentication secure in an existing PHP project or build a solid session layer from scratch, get in touch with me and let's lay a secure foundation together.

Bu kategorideki tüm yazılar →

Devamı için