Как установить время жизни PHP-сессии 30 минут и автоматически её завершать?
Правильная реализация тайм-аута сессии через 30 минут
Ваша проблема типична для начинающих. Дело в том, что настройки session.gc_maxlifetime и session.cookie_lifetime работают не так, как вы ожидаете. session.gc_maxlifetime задаёт максимальное время жизни файла сессии на сервере до того, как сборщик мусора (GC) его удалит. Но GC запускается не при каждом запросе, а с вероятностью 1/100 (по умолчанию). session.cookie_lifetime вообще отвечает за время жизни cookie с идентификатором сессии, а не за саму сессию.
Вот рабочий подход с проверкой времени последней активности:
<?php
session_start();
// Время жизни сессии в секундах (30 минут = 1800 секунд)
$session_lifetime = 1800;
// Проверяем, установлена ли метка времени последней активности
if (isset($_SESSION['LAST_ACTIVITY'])) {
// Вычисляем разницу между текущим временем и временем последней активности
$inactive_time = time() - $_SESSION['LAST_ACTIVITY'];
// Если время бездействия превышает лимит
if ($inactive_time > $session_lifetime) {
// Уничтожаем сессию и все её данные
session_unset();
session_destroy();
// Перенаправляем на страницу входа
header('Location: login.php?timeout=1');
exit;
}
}
// Обновляем метку времени при каждом запросе (активность пользователя)
$_SESSION['LAST_ACTIVITY'] = time();
?>
Ключевые моменты:
- Проверка и обновление — код должен выполняться на каждой странице, где требуется авторизация. Обычно его выносят в отдельный файл (например,
session_check.php) и подключают черезrequire_once. - Порядок действий: сначала проверяем, не истекла ли сессия, затем обновляем метку. Если сделать наоборот, сессия никогда не истечёт.
- Безопасность: после уничтожения сессии обязательно используйте
session_unset()передsession_destroy(), чтобы очистить все переменные сессии. - Продление при активности: этот код автоматически продлевает сессию при каждом действии пользователя (загрузке страницы, AJAX-запросе и т.д.).
Дополнительные настройки для надёжности
Чтобы сборщик мусора не удалял сессию раньше времени, добавьте в начало скрипта:
// Увеличиваем время жизни сессии на сервере
ini_set('session.gc_maxlifetime', $session_lifetime);
// Устанавливаем время жизни cookie сессии
session_set_cookie_params($session_lifetime);
// Запускаем сессию после всех настроек
session_start();
Обратите внимание: session_set_cookie_params() нужно вызывать до session_start(). Это гарантирует, что cookie с идентификатором сессии тоже будет жить 30 минут. Если пользователь закроет браузер раньше — cookie удалится, и сессия завершится.
Полный пример для файла session_check.php:
<?php
$session_lifetime = 1800; // 30 минут
ini_set('session.gc_maxlifetime', $session_lifetime);
session_set_cookie_params($session_lifetime);
session_start();
if (isset($_SESSION['LAST_ACTIVITY'])) {
if (time() - $_SESSION['LAST_ACTIVITY'] > $session_lifetime) {
session_unset();
session_destroy();
header('Location: login.php?timeout=1');
exit;
}
}
$_SESSION['LAST_ACTIVITY'] = time();
?>
Этот подход гарантирует, что сессия будет жить ровно 30 минут с момента последнего действия пользователя. Если пользователь активен — время постоянно обновляется. Если ушёл и вернулся через час — его выкинет на страницу входа.
<<Альтернативный подход: использование базы данных для хранения сессий
Если ваш проект использует базу данных (например, MySQL), рекомендую хранить сессии в БД. Это даёт больше контроля и безопасности. Вот пример реализации:
// Включаем хранение сессий в БД
ini_set('session.save_handler', 'user');
// Функция для открытия сессии
function open_session($save_path, $session_name) {
// Подключение к БД (упрощённо)
global $db;
return true;
}
// Функция для чтения данных сессии
function read_session($session_id) {
global $db;
$stmt = $db->prepare("SELECT data FROM sessions WHERE id = ? AND expiry > NOW()");
$stmt->execute([$session_id]);
$row = $stmt->fetch();
return $row ? $row['data'] : '';
}
// Функция для записи данных сессии
function write_session($session_id, $data) {
global $db;
$expiry = date('Y-m-d H:i:s', time() + 1800); // +30 минут
$stmt = $db->prepare("REPLACE INTO sessions (id, data, expiry) VALUES (?, ?, ?)");
return $stmt->execute([$session_id, $data, $expiry]);
}
// Регистрируем обработчики
session_set_save_handler('open_session', 'close_session', 'read_session', 'write_session', 'destroy_session', 'gc_session');
session_start();
В таблице sessions должно быть поле expiry с типом DATETIME. Сессия автоматически истечёт, когда текущее время превысит значение в этом поле. Плюс такого подхода — вы можете легко реализовать "скользящее" время жизни, обновляя expiry при каждом запросе пользователя.
Для очистки устаревших сессий можно запускать cron-задачу: DELETE FROM sessions WHERE expiry < NOW(). Это надёжнее, чем полагаться на сборщик мусора PHP.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги