Перейти к основному содержимому

Работа с сессиями в PHP

Разработчику Архитектору

Работа с сессиями в PHP

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


Основы HTTP и необходимость сессий

HTTP (HyperText Transfer Protocol) — это протокол прикладного уровня, используемый для передачи гипертекста в интернете. Он работает по принципу "запрос — ответ": клиент (обычно браузер) отправляет запрос на сервер, а сервер возвращает ответ. Каждый такой цикл независим от предыдущего.

Эта особенность делает невозможным автоматическое распознавание пользователя при переходе с одной страницы сайта на другую. Без дополнительных механизмов сервер не может понять, что два запроса пришли от одного и того же человека.

Сессии позволяют создать устойчивый контекст, связывающий несколько HTTP-запросов в одну логическую сессию взаимодействия. Это основа для реализации таких функций, как:

  • аутентификация пользователей;
  • корзина покупок;
  • персонализированные настройки;
  • отслеживание действий пользователя;
  • управление правами доступа.

Как работает сессия в PHP

PHP предоставляет встроенную поддержку сессий через набор функций и суперглобальный массив $_SESSION.


Жизненный цикл сессии

  1. Старт сессии: вызывается функция session_start(). Эта функция пытается найти существующую сессию по идентификатору, переданному клиентом.
  2. Идентификация клиента: если сессия уже существует, PHP считывает её данные из хранилища (по умолчанию — файловой системы). Если сессия новая, создаётся уникальный идентификатор (session_id).
  3. Хранение данных — все данные, помещённые в $_SESSION, автоматически сериализуются и сохраняются на сервере после завершения скрипта.
  4. Передача идентификатора клиенту: PHP устанавливает cookie с именем PHPSESSID, содержащее значение session_id.
  5. Последующие запросы: браузер автоматически отправляет cookie PHPSESSID с каждым запросом к тому же домену. Сервер использует этот идентификатор для загрузки соответствующих данных сессии.
  6. Завершение сессии: сессия может быть завершена явно (session_destroy()) или автоматически по истечении времени жизни (настраивается через session.gc_maxlifetime).

Пример базового использования

<?php
// Запуск сессии
session_start();

// Сохранение данных в сессии
$_SESSION['username'] = 'alice';
$_SESSION['login_time'] = time();

// Чтение данных из сессии
echo "Привет, " . $_SESSION['username'] . "! Вы вошли в " . date('H:i', $_SESSION['login_time']);
?>

Разбор:

  • session_start() инициализирует сессию и загружает данные пользователя по PHPSESSID.
  • Запись в $_SESSION сохраняет состояние между разными HTTP-запросами.
  • time() фиксирует момент входа, а date('H:i', ...) форматирует время для вывода.
  • Через $_SESSION['username'] и $_SESSION['login_time'] видно, как читать сохранённые ранее значения.
  • Это базовый минимальный каркас авторизованной пользовательской сессии.

Хранение данных сессии

По умолчанию PHP хранит данные сессий в виде сериализованных файлов на диске сервера. Путь к этим файлам определяется параметром session.save_path в конфигурации PHP (php.ini).

Файл сессии имеет имя вида sess_<session_id>, где <session_id> — это строка из 32–128 символов (в зависимости от настроек), состоящая из букв и цифр. Внутри файла хранится сериализованное представление массива $_SESSION.

Например, если в сессию записано:

$_SESSION['user_id'] = 123;
$_SESSION['role'] = 'admin';

То содержимое файла будет примерно таким:

user_id|i:123;role|s:5:"admin";

Это формат сериализации PHP, который позволяет точно восстановить типы данных при чтении.


Альтернативные хранилища

PHP поддерживает замену механизма хранения сессий. Можно использовать:

  • базы данных (MySQL, PostgreSQL);
  • in-memory хранилища (Redis, Memcached);
  • распределённые файловые системы.

Для этого реализуется интерфейс SessionHandlerInterface и регистрируется через session_set_save_handler().


Безопасность сессий

Сессии — мощный инструмент, но их неправильное использование создаёт серьёзные уязвимости.


Утечка session_id

Главная угроза — перехват идентификатора сессии злоумышленником. Если он получит PHPSESSID, то сможет подменить пользователя (session fixation или session hijacking).


Защитные меры

  • Использование HTTPS: шифрует весь трафик, включая cookie.
  • Флаг HttpOnly: предотвращает доступ к cookie через JavaScript (document.cookie), защищая от XSS-атак.
  • Флаг Secure: гарантирует, что cookie передаётся только по HTTPS.
  • Флаг SameSite: защищает от CSRF-атак. Рекомендуется значение Lax или Strict.

Настройка в PHP:

ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1); // только если используется HTTPS
ini_set('session.cookie_samesite', 'Lax');

Или в php.ini:

session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = "Lax"

Регенерация идентификатора

После успешной аутентификации обязательно нужно сгенерировать новый идентификатор сессии:

session_regenerate_id(true); // true — удаляет старый файл сессии

Это предотвращает атаку session fixation, когда злоумышленник заранее даёт жертве ссылку с известным PHPSESSID.


Время жизни сессии

Сессии не должны жить вечно. Настройки:

  • session.gc_maxlifetime — время в секундах, после которого неактивная сессия считается "мёртвой" и может быть удалена сборщиком мусора.
  • Рекомендуется устанавливать значение от 1800 (30 минут) до 7200 (2 часа) для обычных приложений.

Также можно реализовать собственную логику проверки активности:

if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > 1800)) {
session_unset();
session_destroy();
// Перенаправление на страницу входа
}
$_SESSION['last_activity'] = time();

Разбор:

  • Код реализует timeout неактивности: если пользователь долго не делал запросов, сессия принудительно закрывается.
  • time() - $_SESSION['last_activity'] > 1800 означает порог 30 минут.
  • session_unset() очищает переменные сессии, а session_destroy() уничтожает саму сессию.
  • После проверки метка last_activity обновляется текущим временем для следующего запроса.
  • Такой контроль снижает риск использования "забытых" открытых сессий.

Аутентификация и авторизация через сессии

Сессии являются основой для реализации систем входа и управления ролями.


Страница регистрации

Регистрация — это процесс создания нового аккаунта. Она включает:

  1. Приём данных формы (логин, email, пароль).
  2. Валидацию данных (формат email, сложность пароля).
  3. Хеширование пароля.
  4. Сохранение в базу данных.

Никогда не храните пароли в открытом виде!

PHP предоставляет надёжные функции для хеширования:

$password_hash = password_hash($password, PASSWORD_ARGON2ID);
// или
$password_hash = password_hash($password, PASSWORD_DEFAULT);

Пример обработчика регистрации:

Код ITЗагрузка примера кода…


Страница входа

Вход — это проверка учётных данных и установка сессии.

Код ITЗагрузка примера кода…

Разбор:

  • Обработчик входа начинает с session_start(), чтобы было куда записать данные авторизации.
  • Через PDO::prepare(...)->execute(...) выполняется безопасный запрос пользователя из БД.
  • password_verify(...) сравнивает введённый пароль с хешем из базы корректным криптографическим способом.
  • После успешной проверки вызывается session_regenerate_id(true) для защиты от session fixation.
  • В $_SESSION сохраняются ключевые признаки входа (user_id, username, role, logged_in) для дальнейших проверок доступа.

Обратите внимание:

  • Используется password_verify() для сравнения пароля с хешем.
  • После успешного входа вызывается session_regenerate_id(true).
  • В сессию записываются только необходимые данные — user_id, username, role.

Проверка авторизации на защищённых страницах

Любая страница, требующая входа, должна начинаться с проверки сессии:

<?php
session_start();

if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
header("Location: login.php");
exit;
}

// Теперь можно работать с данными пользователя
echo "Добро пожаловать, " . htmlspecialchars($_SESSION['username']);
?>

Для защиты от XSS всегда используйте htmlspecialchars() при выводе данных, полученных от пользователя.


Реализация системы ролей

Роли позволяют ограничивать доступ к функционалу в зависимости от привилегий пользователя.


Простая модель ролей

Предположим, есть три роли:

  • guest — неавторизованный пользователь;
  • user — обычный пользователь;
  • admin — администратор.

В сессии хранится поле role.

Проверка прав:

Код ITЗагрузка примера кода…

Использование:

<?php
requireRole('admin');
// Только администраторы могут видеть эту страницу
?>
<h1>Панель администратора</h1>

Отображение контента в зависимости от роли

Код ITЗагрузка примера кода…


Под капотом — как PHP управляет сессиями

Когда вызывается session_start():

  1. PHP проверяет наличие cookie PHPSESSID в запросе.
  2. Если cookie есть, извлекается session_id.
  3. Выполняется валидация session_id (только буквенно-цифровые символы, длина соответствует настройкам).
  4. PHP обращается к хранилищу (файл, Redis и т.д.) по этому идентификатору.
  5. Если данные найдены, они десериализуются в $_SESSION.
  6. Если cookie нет или сессия не найдена, создаётся новый session_id.
  7. В ответе устанавливается заголовок Set-Cookie: PHPSESSID=....
Set-Cookie: PHPSESSID=...

Важно: session_start() должен вызываться до любого вывода на экран, так как он отправляет HTTP-заголовки.


Распространённые ошибки

  1. Забыли вызвать session_start() — данные сессии недоступны.
  2. Хранение паролей в сессии — никогда не делайте этого. Даже хеши.
  3. Отсутствие регенерации ID после входа — уязвимость к session fixation.
  4. Отсутствие HTTPS — session_id передаётся в открытом виде.
  5. Хранение слишком много данных в сессии — увеличивает нагрузку на сервер и замедляет работу.
  6. Использование == вместо === при проверке флагов — может привести к логическим ошибкам ("1" == true, но "1" !== true).

Продвинутые практики

Автоматический выход по неактивности

// В начале каждого скрипта
session_start();
$timeout = 1800; // 30 минут

if (isset($_SESSION['last_activity']) && (time() - $_SESSION['last_activity'] > $timeout)) {
session_unset();
session_destroy();
header("Location: logout.php?timeout=1");
exit;
}
$_SESSION['last_activity'] = time();

Защита от одновременного входа с разных устройств

Можно хранить хеш от отпечатка устройства (user-agent + IP) и проверять его при каждом запросе:

$fingerprint = hash('sha256', $_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR']);
if (!isset($_SESSION['fingerprint'])) {
$_SESSION['fingerprint'] = $fingerprint;
} elseif ($_SESSION['fingerprint'] !== $fingerprint) {
// Возможна кража сессии
session_destroy();
die("Подозрительная активность");
}

⚠️ Внимание: IP может меняться у мобильных пользователей, поэтому такой метод подходит не для всех случаев.


Расширенные сценарии — регистрация, вход и управление ролями

Структура проекта для системы аутентификации

Для реализации полноценной системы аутентификации рекомендуется следующая структура файлов:

/auth/
├── register.php # Страница регистрации
├── login.php # Страница входа
├── logout.php # Выход из системы
├── dashboard.php # Защищённая страница после входа
/includes/
├── db.php # Подключение к базе данных
├── auth.php # Вспомогательные функции аутентификации
└── helpers.php # Общие утилиты (htmlspecialchars, редиректы и т.п.)
/assets/
└── style.css # Стили (опционально)
index.php # Главная страница

Такая структура обеспечивает чёткое разделение ответственности и упрощает поддержку кода.


Подключение к базе данных

Файл /includes/db.php:

<?php
$host = 'localhost';
$dbname = 'my_app';
$username = 'db_user';
$password = 'secure_password';

try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Ошибка подключения к БД: " . htmlspecialchars($e->getMessage()));
}
?>

Использование utf8mb4 гарантирует поддержку эмодзи и всех символов Unicode.


Вспомогательные функции аутентификации

Файл /includes/auth.php:

Код ITЗагрузка примера кода…

Эти функции позволяют централизованно управлять проверками доступа.


Страница регистрации — подробный разбор

Файл /auth/register.php:

Код ITЗагрузка примера кода…


Ключевые моменты

  • Все входные данные проходят валидацию.
  • Используется FILTER_SANITIZE_EMAIL и FILTER_VALIDATE_EMAIL.
  • Хеширование пароля выполняется через password_hash() с алгоритмом PASSWORD_ARGON2ID.
  • После успешной регистрации пользователь автоматически входит в систему (это повышает UX).
  • Все выводимые строки экранируются через htmlspecialchars().

Страница входа — безопасная реализация

Файл /auth/login.php:

Код ITЗагрузка примера кода…

💡 Совет: Поле identifier вместо отдельных username и email упрощает интерфейс и соответствует современным практикам (например, как в GitHub или Google).


Выход из системы

Файл /auth/logout.php:

Код ITЗагрузка примера кода…

Этот скрипт полностью уничтожает сессию и удаляет cookie, предотвращая повторное использование старого PHPSESSID.


Защищённая страница с проверкой роли

Файл /dashboard.php:

Код ITЗагрузка примера кода…

Такой подход позволяет гибко управлять контентом на основе ролей без дублирования логики.


Продвинутая защита — CSRF и дополнительные меры

Защита от CSRF (Cross-Site Request Forgery)

Добавьте в каждую форму скрытое поле с токеном:

// Генерация токена при старте сессии (или при первом запросе)
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

В форме:

<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">

Проверка при обработке:

if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
die("Недопустимый запрос");
}

Использование hash_equals() предотвращает атаки по времени (timing attacks).


Альтернативы сессиям — stateless-аутентификация

Хотя сессии — стандартный способ управления состоянием в PHP, современные API часто используют токены (например, JWT). Однако для классических веб-приложений с формами и HTML-рендерингом сессии остаются наиболее простым и надёжным решением.

JWT требует:

  • хранения токена на клиенте (в localStorage или cookie);
  • подписи токена секретным ключом;
  • проверки срока действия при каждом запросе;
  • механизма отзыва токенов (что усложняет архитектуру).

Для большинства сайтов на PHP сессии предпочтительнее.


Резюме по безопасности сессий

МераНазначение
session.cookie_httponly = 1Защита от XSS
session.cookie_secure = 1Только по HTTPS
session.cookie_samesite = "Lax"Защита от CSRF
session_regenerate_id(true) после входаЗащита от session fixation
Хранение только user_id, а не пароляМинимизация рисков
Использование password_hash() и password_verify()Безопасное хранение паролей
Время жизни сессии ≤ 2 часовОграничение окна атаки

Восстановление пароля по email

Восстановление пароля — обязательная функция любого приложения с аутентификацией. Она позволяет пользователю получить доступ к аккаунту, если он забыл пароль.


Общая схема восстановления

  1. Пользователь указывает email или логин на странице восстановления.
  2. Система проверяет существование пользователя.
  3. Генерируется одноразовый токен с ограниченным сроком действия.
  4. Токен сохраняется в базе данных и отправляется пользователю по email в виде ссылки.
  5. При переходе по ссылке система проверяет токен.
  6. Если токен действителен, пользователь может задать новый пароль.

Безопасные практики

  • Токен должен быть случайным, длиной не менее 64 байт (128 символов в hex).
  • Срок действия токена — от 15 до 60 минут.
  • Одноразовость: после использования токен удаляется.
  • Не раскрывать, существует ли пользователь с таким email (чтобы не помогать брутфорсу).

Реализация

1. Форма запроса восстановления (/auth/forgot.php)

Код ITЗагрузка примера кода…


2. Страница сброса (/auth/reset.php)

Код ITЗагрузка примера кода…


3. Структура таблицы password_resets

CREATE TABLE password_resets (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
token CHAR(64) NOT NULL UNIQUE,
expires_at DATETIME NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

Журналирование событий входа

Для аудита безопасности рекомендуется вести журнал всех попыток входа.


Таблица login_attempts

CREATE TABLE login_attempts (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
ip_address VARCHAR(45),
user_agent TEXT,
success BOOLEAN,
attempted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Запись события

Добавьте в обработчик входа:

function logLoginAttempt($username, $success) {
global $pdo;
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';

$stmt = $pdo->prepare("
INSERT INTO login_attempts (username, ip_address, user_agent, success)
VALUES (?, ?, ?, ?)
");
$stmt->execute([$username, $ip, $ua, (bool)$success]);
}

Вызов:

if ($user && password_verify($password, $user['password_hash'])) {
// успешный вход
logLoginAttempt($username, true);
// ... остальное
} else {
logLoginAttempt($username, false);
$error = "Неверный логин или пароль";
}

Это позволяет:

  • выявлять брутфорс-атаки;
  • анализировать подозрительную активность;
  • предоставлять данные при расследовании инцидентов.

Двухфакторная аутентификация (2FA)

Двухфакторная аутентификация повышает безопасность за счёт добавления второго фактора (обычно временный код из приложения или SMS).


Простая реализация с TOTP

  1. При первом включении 2FA генерируется секретный ключ.
  2. Ключ сохраняется в БД и отображается пользователю в виде QR-кода.
  3. При входе после ввода пароля запрашивается код из Google Authenticator.
  4. Сервер проверяет код с помощью библиотеки (например, robthree/twofactorauth).

Установка через Composer

composer require robthree/twofactorauth

Активация 2FA

use RobThree\Auth\TwoFactorAuth;

$tfa = new TwoFactorAuth('Вселенная IT');
$secret = $tfa->createSecret(); // 16-символьный base32 ключ

// Сохранить в users.totp_secret
// Показать QR-код: $tfa->getQRCodeImageAsDataUri($email, $secret);

Проверка кода при входе

if (isset($_SESSION['pending_2fa'])) {
// Пользователь уже прошёл пароль, ждём код
if ($_POST['code'] && $tfa->verifyCode($_SESSION['totp_secret'], $_POST['code'])) {
$_SESSION['logged_in'] = true;
unset($_SESSION['pending_2fa']);
unset($_SESSION['totp_secret']);
header("Location: /dashboard.php");
exit;
} else {
$error = "Неверный код двухфакторной аутентификации";
}
}

Полная реализация требует отдельной страницы настройки 2FA, но даже базовая версия значительно повышает защиту.


Тестирование сессий

Для надёжности важно тестировать сценарии работы с сессиями.


Пример теста на PHPUnit (без фреймворка)

Код ITЗагрузка примера кода…

Ключевые сценарии для тестирования:

  • успешный вход;
  • неверный пароль;
  • пустые поля;
  • регенерация session_id;
  • выход из системы;
  • истечение срока сессии.

Распространённые проблемы и их решение

ПроблемаПричинаРешение
Сессия не сохраняется между страницамиsession_start() вызван после выводаВызывать session_start() в самом начале скрипта
Все пользователи видят чужие данныеОдин и тот же PHPSESSID используется всемиПроверить, не установлен ли session_id() вручную без генерации
Сессия живёт слишком долгоgc_maxlifetime слишком большоеУменьшить значение, добавить собственную проверку времени
CSRF-атаки работаютОтсутствует защита токеномВнедрить csrf_token во все формы
XSS приводит к краже сессииCookie без HttpOnlyУстановить session.cookie_httponly = 1

Сессии и современные архитектурные подходы

Современные веб-приложения всё чаще строятся по принципу разделения фронтенда и бэкенда — фронтенд — это SPA (Single Page Application) на React, Vue или Angular, а бэкенд — REST API или GraphQL-сервер на PHP, Node.js, Python и т.д. В такой архитектуре классические PHP-сессии теряют актуальность.


Почему сессии не подходят для stateless API

RESTful API предполагает stateless взаимодействие: каждый запрос должен содержать всю необходимую информацию для его обработки. Сервер не хранит состояние между запросами. Это упрощает масштабирование, кэширование и отказоустойчивость.

PHP-сессии нарушают этот принцип:

  • они требуют хранения состояния на сервере;
  • они привязаны к конкретному экземпляру сервера (если нет общего хранилища);
  • они зависят от cookie, что усложняет кросс-доменные запросы.

Поэтому в API-ориентированных системах вместо сессий используют токены, чаще всего JWT (JSON Web Token).


Когда сессии остаются уместными

Сессии идеально подходят для:

  • классических веб-сайтов с HTML-рендерингом на стороне сервера;
  • внутренних корпоративных систем;
  • приложений с минимальной нагрузкой и простой архитектурой;
  • случаев, когда требуется строгий контроль над временем жизни сессии и возможностью её принудительного завершения.

Если вы разрабатываете сайт, где PHP генерирует HTML (например, через шаблонизатор Twig или просто echo), сессии — правильный выбор.


Альтернатива — JWT (JSON Web Token)

JWT — это самодостаточный токен, содержащий закодированную информацию о пользователе и сроке действия. Он подписывается секретным ключом, что гарантирует его подлинность.


Пример использования JWT в PHP

Установка через Composer:

composer require firebase/php-jwt

Генерация токена:

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$key = "your_secret_key";
$payload = [
"user_id" => 123,
"username" => "alice",
"role" => "user",
"exp" => time() + 3600 // 1 час
];

$jwt = JWT::encode($payload, $key, 'HS256');
echo $jwt;

Проверка токена:

try {
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
// Доступ к данным: $decoded->user_id, $decoded->role и т.д.
} catch (Exception $e) {
// Невалидный или просроченный токен
http_response_code(401);
die("Недействительный токен");
}

В отличие от сессий:

  • JWT не требует хранения на сервере;
  • он может быть передан в заголовке Authorization: Bearer <token>;
  • он работает без cookie, что удобно для мобильных и SPA-приложений.

Однако у JWT есть недостаток: невозможно отозвать токен до истечения срока действия, если не вести чёрный список (что сводит преимущества к нулю). Поэтому для высокозащищённых систем часто комбинируют JWT с коротким сроком жизни и механизмом refresh-токенов.


Сравнение — сессии и JWT

КритерийСессииJWT
Хранение состоянияНа сервереВ самом токене
МасштабируемостьТребует общего хранилища (Redis)Stateless — легко масштабируется
БезопасностьЗависит от защиты cookie и IDЗависит от секретного ключа и алгоритма
Отзыв доступаМгновенно (session_destroy())Только через чёрный список или короткий TTL
Поддержка CORSОграничена (cookie third-party блокируются)Полная (через заголовки)
Использование в SPAНе рекомендуетсяРекомендуется

Выбор зависит от архитектуры проекта. Для монолитного PHP-сайта — сессии. Для микросервисов и SPA — JWT.


Практические рекомендации по работе с сессиями

1. Настройка php.ini для продакшена

Код ITЗагрузка примера кода…


2. Обёртка для работы с сессиями

Создайте класс SessionManager, чтобы централизовать логику:

Код ITЗагрузка примера кода…

Использование:

SessionManager::set('user_id', 123);
if (SessionManager::isLoggedIn()) {
// показать панель пользователя
}

Такой подход упрощает тестирование и замену механизма хранения в будущем.


Тестирование сессий вручную

Перед запуском в продакшен проверьте:

  1. Cookie устанавливаются правильно:
    Откройте DevTools → Application → Cookies → убедитесь, что PHPSESSID имеет флаги HttpOnly, Secure (если HTTPS), SameSite=Lax.

  2. ID меняется после входа:
    Зайдите на сайт как гость → запомните PHPSESSID → войдите → убедитесь, что ID изменился.

  3. Выход уничтожает сессию:
    После выхода cookie должна исчезнуть или стать пустой.

  4. Повторное использование старого ID не работает:
    Скопируйте старый PHPSESSID после выхода → попробуйте использовать → должно перенаправить на вход.


Распространённые ошибки даже у опытных разработчиков

  1. Хранение пароля в сессии — даже хеша.
    → Храните только user_id и роль.

  2. Отсутствие session_regenerate_id() после входа.
    → Это открывает дверь для session fixation.

  3. Использование == вместо === при проверке флагов.
    "1" == true, но "1" !== true.

  4. Забытый exit после header("Location: ...").
    → Скрипт продолжает выполняться, что может привести к утечке данных.

  5. Вывод до session_start().
    → Вызовет ошибку "Cannot send session cookie — headers already sent".


Практика — минимальный SessionGuard для проекта

Чтобы избежать разрозненных проверок авторизации, вынесите их в один модуль:

Код ITЗагрузка примера кода…

Такой слой снижает количество ошибок и задает единый стандарт для всех защищенных страниц.


Где эта тема применяется дальше


Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.

Содержание