W3docs

PHP-сессии: полное руководство

Как работают PHP-сессии, как хранить и получать данные сессий и защищать их от атак с подменой и перехватом идентификатора.

HTTP — протокол без сохранения состояния: каждый запрос браузера независим, и сервер забывает всё, как только отправляет ответ. Сессии — это механизм, с помощью которого PHP запоминает посетителя между запросами: они позволяют удерживать пользователя в системе, строить корзину покупок или сохранять настройки по мере перехода со страницы на страницу. В этом руководстве рассматривается, что такое сессии, как они работают изнутри, как читать и записывать данные сессий и как обеспечить их безопасность.

Что такое PHP-сессии?

PHP-сессия — это механизм хранения пользовательских данных на стороне сервера на протяжении всего визита пользователя. В отличие от куков, которые хранят данные в браузере, сессия хранит сами данные на сервере и отправляет браузеру лишь небольшой идентификатор сессии, чтобы определить, кому принадлежат данные.

Это важно по двум причинам:

  • Объём — куки ограничены примерно 4 КБ и хранятся в браузере; данные сессии хранятся в серверном хранилище (файлах, базе данных или памяти) и могут быть значительно больше.
  • Безопасность — конфиденциальные значения (идентификатор пользователя, роль или содержимое корзины) никогда не покидают сервер, поэтому браузер не может их прочитать или подделать. Наружу передаётся только непрозрачный идентификатор сессии.

Как работают PHP-сессии?

При запуске сессии PHP генерирует уникальный идентификатор сессии для посетителя и отправляет его браузеру в куке с именем PHPSESSID. При каждом последующем запросе браузер возвращает эту куку, и PHP использует идентификатор для поиска соответствующих данных, хранящихся на сервере. Сами данные доступны вашему коду через array $_SESSION.

Рабочий процесс сессии

graph LR
A[Browser] -- 1. Request + Session Cookie --> B[Server]
B -- 2. Validate Cookie & Fetch Data --> A
A -- 3. Receive Response --> B

Коротко: кука содержит идентификатор; сервер хранит данные.

Запуск сессии

Каждая страница, которая читает или записывает данные сессии, должна вызывать session_start() до того, как в браузер будут отправлены какие-либо данные. Поскольку session_start() отправляет куку PHPSESSID через HTTP-заголовок, даже один пробел или пустая строка перед открывающим тегом <?php вызовет предупреждение «headers already sent» и сломает сессию.

Вызов session_start() либо возобновляет существующую сессию посетителя (если браузер прислал действительный идентификатор), либо создаёт новую. Проверка через session_status() позволяет избежать предупреждения, если сессия уже была запущена ранее в том же запросе:

Как запустить PHP-сессию

<?php
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

Чтение и запись данных сессии

После запуска сессии суперглобальная переменная $_SESSION ведёт себя как обычный ассоциативный array. Присвойте значение ключу для его сохранения:

Сохранение данных в PHP-сессии

<?php
$_SESSION['username'] = 'John Doe';
$_SESSION['cart'] = ['book', 'pen'];

Считайте данные на той же странице или на любой последующей странице в рамках той же сессии:

Получение данных из PHP-сессии

<?php
// Always check the key exists to avoid a warning
$username = $_SESSION['username'] ?? 'Guest';

echo "Welcome, {$username}";

Поскольку данные сохраняются между запросами, распространённый паттерн — счётчик просмотров страниц, который выживает при перезагрузках:

Подсчёт просмотров страниц в текущей сессии

<?php
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}

$_SESSION['views'] = ($_SESSION['views'] ?? 0) + 1;

echo "You have viewed this page {$_SESSION['views']} time(s).";

Чтобы удалить одно значение, используйте unset() по его ключу — не присваивайте null, это оставит ключ в массиве:

<?php
unset($_SESSION['cart']);

Сессии и куки

Сессии и куки часто работают вместе, но хранят данные в разных местах. Используйте сессию, когда данные конфиденциальны или велики; используйте куку, когда браузер сам должен что-то помнить (например, токен «запомнить меня») между визитами.

СессияКука
Хранится наСервереБраузере
Видна пользователюНет (только идентификатор)Да
Ограничение размераБольшое (серверное хранилище)~4 КБ
Время жизниДо закрытия браузера или тайм-аутаНастраиваемый срок

Защита PHP-сессий

Важно защитить PHP-сессии, чтобы предотвратить несанкционированный доступ к конфиденциальным данным пользователей. Существует несколько способов защитить PHP-сессии:

  • Периодически обновляйте идентификатор сессии.
  • Храните данные сессии на сервере в защищённом каталоге.
  • Используйте HTTPS для защиты передачи данных сессии.

Обновление идентификатора сессии и усиление защиты куки

Параметры усиления защиты необходимо установить до вызова session_start(), иначе кука уже будет отправлена со старыми настройками. Обновление идентификатора сразу после изменения привилегий (например, входа в систему) предотвращает атаки подмены сессии, при которых злоумышленник вынуждает жертву использовать известный ему идентификатор сессии:

<?php
// Configure before the session starts
ini_set('session.cookie_secure', '1');   // send cookie over HTTPS only
ini_set('session.use_only_cookies', '1'); // never accept the ID from the URL
ini_set('session.cookie_httponly', '1');  // hide the cookie from JavaScript

session_start();

// After a successful login, swap the ID and discard the old one
session_regenerate_id(true);
НастройкаОт чего защищает
cookie_secureУтечка идентификатора сессии через HTTP
cookie_httponlyКража куки через JavaScript (XSS)
use_only_cookiesПередача идентификатора сессии в URL
session_regenerate_idПодмена сессии после входа в систему

Завершение PHP-сессии

Чтобы выйти из системы, очистите данные и уничтожьте сессию. Очистка $_SESSION удаляет переменные; session_destroy() удаляет данные на сервере; удаление куки не позволяет браузеру отправлять устаревший идентификатор:

<?php
session_start();

// 1. Clear all session variables
$_SESSION = [];

// 2. Delete the session cookie in the browser
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 data stored on the server
session_destroy();

Заключение

PHP-сессии — незаменимый инструмент для хранения пользовательских данных на стороне сервера и улучшения пользовательского опыта на вашем сайте. Понимая принципы их работы и умея их использовать, вы сможете в полной мере воспользоваться преимуществами, которые они предоставляют. При наличии надлежащих мер безопасности вы также обеспечите защиту конфиденциальных данных пользователей.

Практика

Практика
Что можно реализовать с помощью PHP-сессий?
Что можно реализовать с помощью PHP-сессий?
Was this page helpful?