Я хотел бы увеличить тайм-аут сеанса в php
Я знаю, что это можно сделать, изменив файл php.ini. Но у меня нет доступа к нему.
Так можно ли это сделать только с php-кодом?
Тайм-аут сеанса – это понятие, которое должно быть реализовано в коде, если вы хотите получить строгие гарантии; это единственный способ, которым вы можете быть абсолютно уверены, что никакая сессия никогда не выживет после X минут бездействия.
Если ослабление этого требования немного приемлемо, и вы в порядке с размещением нижней границы вместо строгого ограничения продолжительности, вы можете сделать это легко и без написания пользовательской логики.
Если ваши сеансы реализованы с помощью файлов cookie (они, вероятно, есть), а если клиенты не злонамерены, вы можете установить верхнюю границу продолжительности сеанса, настроив определенные параметры. Если вы используете обработку сессий по умолчанию PHP с помощью файлов cookie, установка session.gc_maxlifetime
вместе с session_set_cookie_params
должно работать для вас следующим образом:
// server should keep session data for AT LEAST 1 hour ini_set('session.gc_maxlifetime', 3600); // each client should remember their session id for EXACTLY 1 hour session_set_cookie_params(3600); session_start(); // ready to go!
Это работает путем настройки сервера для хранения данных сеанса в течение как минимум одного часа бездействия и указания вашим клиентам, что они должны «забыть» свой идентификатор сеанса после того же времени. Оба этих этапа необходимы для достижения ожидаемого результата.
Если вы не сообщите клиентам, чтобы они забыли свой идентификатор сеанса через час (или, если клиенты злонамерены и решили игнорировать ваши инструкции), они будут продолжать использовать один и тот же идентификатор сеанса, и его эффективная продолжительность будет недетерминированной. Это связано с тем, что сеансы, срок службы которых истек на серверной стороне, не собираются сразу же с мусором, а только всякий раз, когда начинается сеанс GC .
GC является потенциально дорогостоящим процессом, поэтому обычно вероятность будет небольшой или даже нулевой (веб-сайт, получающий огромное количество хитов, вероятно, будет полностью отказываться от вероятностного GC и планировать его в фоновом режиме каждые X минут). В обоих случаях (при условии отсутствия сотрудничающих клиентов) нижняя граница для эффективного времени жизни сеанса будет session.gc_maxlifetime
, но верхняя граница будет непредсказуемой.
Если вы не установите session.gc_maxlifetime
в тот же промежуток времени, сервер может отбросить данные сеанса бездействия раньше этого; в этом случае клиент, который все еще помнит свой идентификатор сеанса, представит его, но сервер не найдет никаких данных, связанных с этим сеансом, эффективно ведет себя так, как будто сеанс только что начался.
Вы можете сделать вещи полностью контролируемыми, используя пользовательскую логику, чтобы также установить верхнюю границу неактивности сессии; вместе с нижней границей сверху это приводит к строгой настройке.
Сделайте это, сохранив верхнюю границу вместе с остальными данными сеанса:
session_start(); // ready to go! $now = time(); if (isset($_SESSION['discard_after']) && $now > $_SESSION['discard_after']) { // this session has worn out its welcome; kill it and start a brand new one session_unset(); session_destroy(); session_start(); } // either new or old, it should live at most for another hour $_SESSION['discard_after'] = $now + 3600;
До сих пор мы не интересовались точными значениями каждого идентификатора сеанса, только с требованием, чтобы данные существовали до тех пор, пока они нам нужны. Имейте в виду, что в (маловероятном) случае, что для вас важны сеансы, необходимо позаботиться о том, чтобы восстановить их с помощью session_regenerate_id
когда это необходимо.
Если вы используете обработку сеанса PHP по умолчанию, единственным способом надежно изменить продолжительность сеанса на всех платформах является изменение php.ini . Это связано с тем, что на некоторых платформах сбор мусора реализуется через скрипт, который запускается каждый определенный срок ( cron- скрипт), который читается непосредственно из php.ini , и поэтому любые попытки его изменения во время выполнения, например, через ini_set()
, ненадежны и, скорее всего, не сработает.
Например, в системах Debian Linux сбор мусора выполняется через /etc/cron.d/php5, который выполняется в XX: 09 и XX: 39 (то есть каждые полчаса), и если он находит сеанс старше сеанса .gc_maxlifetime, указанное в php.ini , то этот сеанс удаляется без пощады. Это также объясняет, почему в этом вопросе: PHP-сессии слишком быстро выходят из строя , у ОП были проблемы в одном хосте, но проблемы прекратились при переключении на другой хост.
Итак, учитывая, что у вас нет доступа к php.ini , если вы хотите сделать это переносимо, использование сеанса по умолчанию не является вариантом. По-видимому, продление срока действия файла cookie было достаточно для вашего хоста, но если вы хотите, чтобы решение работало надежно, даже если вы переключаете хосты, вы должны использовать другую альтернативу.
Доступные альтернативные методы включают:
Установите другой сеансовый (save) обработчик в PHP, чтобы сохранить свои сеансы в другом каталоге или в базе данных, как указано в PHP: пользовательские обработчики сеансов (руководство PHP) , так что задание cron не достигает его, и только PHP происходит внутренняя сборка мусора. Этот параметр, вероятно, может использовать ini_set()
для установки session.gc_maxlifetime, но я предпочитаю просто игнорировать параметр maxlifetime в моем обратном вызове gc()
и определять максимальный срок службы самостоятельно.
Полностью забудьте о внутренней обработке сессий PHP и выполните собственное управление сеансом. Этот метод имеет два основных недостатка: вам понадобятся ваши собственные глобальные переменные сеанса, поэтому вы теряете преимущество суперзвезды $_SESSION
, и ему нужен больше кода, поэтому есть больше возможностей для ошибок и недостатков безопасности. Самое главное, идентификатор сеанса должен быть сформирован из криптографически безопасных случайных или псевдослучайных чисел, чтобы избежать предсказуемости идентификатора сеанса (что приводит к возможному захвату сеанса), и это не так просто сделать с PHP портативно. Главное преимущество заключается в том, что он будет работать последовательно на всех платформах, и вы полностью контролируете код. Это подход, к которому относится, например, программное обеспечение форума phpBB (по крайней мере, версия 1, я не уверен в более поздних версиях).
В документации для session_set_save_handler()
есть пример (1 session_set_save_handler()
. Пример длинный, но я воспроизведу его здесь, с соответствующими изменениями, необходимыми для продления продолжительности сеанса. Обратите внимание на включение session_set_cookie_params()
чтобы увеличить время жизни файла cookie.
<?php class FileSessionHandler { private $savePath; private $lifetime; function open($savePath, $sessionName) { $this->savePath = 'my_savepath'; // Ignore savepath and use our own to keep it safe from automatic GC $this->lifetime = 3600; // 1 hour minimum session duration if (!is_dir($this->savePath)) { mkdir($this->savePath, 0777); } return true; } function close() { return true; } function read($id) { return (string)@file_get_contents("$this->savePath/sess_$id"); } function write($id, $data) { return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true; } function destroy($id) { $file = "$this->savePath/sess_$id"; if (file_exists($file)) { unlink($file); } return true; } function gc($maxlifetime) { foreach (glob("$this->savePath/sess_*") as $file) { if (filemtime($file) + $this->lifetime < time() && file_exists($file)) { // Use our own lifetime unlink($file); } } return true; } } $handler = new FileSessionHandler(); session_set_save_handler( array($handler, 'open'), array($handler, 'close'), array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc') ); // the following prevents unexpected effects when using objects as save handlers register_shutdown_function('session_write_close'); session_set_cookie_params(3600); // Set session cookie duration to 1 hour session_start(); // proceed to set and retrieve values by key from $_SESSION
Подход (2) сложнее; в основном, вам необходимо повторно реализовать все функции сеанса самостоятельно. Здесь я не буду вдаваться в подробности.
Нет. Если у вас нет доступа к php.ini, вы не можете гарантировать, что изменения будут иметь какой-либо эффект.
Я сомневаюсь, что вам нужно продлить время сеанса.
На данный момент у него довольно разумный тайм-аут, и нет причин его продлевать.
Вы можете переопределить значения в php.ini из вашего PHP-кода, используя ini_set()
.
Поместите $_SESSION['login_time'] = time();
на предыдущую страницу аутентификации. И снимок внизу на каждой другой странице, где вы хотите проверить тайм-аут сеанса.
if(time() - $_SESSION['login_time'] >= 1800){ header("Location: logout.php"); //redirect if the page is inactive for 30 minutes } else { $_SESSION['login_time'] = time(); // update value of session }