Как запретить уничтожение сессии php
Модуль сессии не гарантирует, что хранимая сессионная информация доступна только пользователю, который создал сессию. Необходимо принять дополнительные меры по защите конфиденциальности сессии, основываясь на связанных с ней данных.
Оценка важности данных, передаваемых в рамках сессии, важна для выбора мер по защите этой информации; все имеет свою цену и обычно дополнительные меры защиты приводят к ухудшению удобства для конечного пользователя. Например, если необходимо защитить пользователя от простейших методов социальной инженерии, следует включить session.use_only_cookies. В данном случае со стороны пользовательского ПО обязательна поддержка cookie, иначе механизм сессий не будет работать.
Существует несколько способов утечки существующего идентификатора сессии третьим лицам. Например инъекции JavaScript, передача идентификатора сессии в URL, перехват пакетов, физический доступ к устройству и т.д. Перехваченный идентификатор сессии позволит третьим лицам получить доступ ко всем ресурсам, связанным с данной сессией. Во-первых, передача идентификатора сессии в URL. При переходе на внешний сайт идентификатор сессии пользователя и адрес ресурса могут попасть в статистику переходов данного сайта. Во-вторых, при более активной атаке возможно прослушивание сетевого трафика злоумышленником. Если канал передачи данных не зашифрован, идентификаторы сессии будут переданы в виде простого текста. В таком случае решением является обязательное использование SSL/TLS пользователями при доступе к сайту. Для этих целей следует применять HSTS.
Замечание: Даже HTTPS иногда может не защитить конфиденциальные данные. Например, уязвимости типа CRIME, BEAST могут позволить злоумышленнику получить доступ к данным. Многие сети используют прокси HTTPS MITM для аудита. Атакующие также могут настроить такие прокси.
Неадаптивное управление сессиями
В настоящее время PHP использует адаптивное управление сессиями по умолчанию. Адаптивное управление сессиями несёт дополнительные риски.
Если session.use_strict_mode включён и обработчик сохранения сессии это поддерживает, неинициализированный сессионный ID отвергается и создаётся новый. Это защищает от атак, которые принуждают пользователя использовать заранее известный ID. Атакующий может размещать ссылки или отправлять письма, которые содержат сессионный ID. Например http://example.com/page.php?PHPSESSID=123456789 . Если опция session.use_trans_sid включена, то жертва откроет сессию с этим идентификатором. Опция session.use_strict_mode уменьшает этот риск.
Внимание
Определённый пользователем обработчик сохранения также может поддерживать строгий сессионный режим, путём реализации функции/метода проверки корректности идентификатора сессии. Все определённые пользователем обработчики сохранения обязаны его реализовывать.
Cookie с сессионным ID должна устанавливаться с указанием параметров domain, path, httponly, secure и, начиная с PHP 7.3, атрибут SameSite. Их приоритетность определяется браузерами. Опираясь на эту приоритетность, атакующий может установить сессионный ID, который будет использоваться бесконечно. Применение session.use_only_cookies не решает эту проблему. session.use_strict_mode уменьшает риск. session.use_strict_mode=On, не допускает использование неинициализированных сессионных ID.
Замечание: Даже при уменьшении риска с помощью session.use_strict_mode атакующий всё ещё может заставить пользователя использовать уже инициализированную сессию, созданную атакующим. Например JavaScript-инъекция. Эта атака может быть смягчена, если следовать рекомендациям этого руководства. Если вы следуете этому руководству, вы должны включить session.use_strict_mode, использовать управление сессиями на основе временных меток и пересоздавать идентификатор сессии с помощью session_regenerate_id() , как рекомендуется. Если вы всё это сделаете, идентификатор сессии злоумышленника в итоге будет удалён. Если произошёл доступ к истёкшей сессией, вы должны сохранить все данные активных сессий пользователя. Это позволит для дальнейшего расследования причин произошедшего. После этого, принудительно заставьте пользователя выйти из всех активных сессий, то есть потребуйте от пользователей переавторизации. Это позволит предотвратить атаку с использованием краденной сессии.
Внимание
Доступ к истёкшей сессии не всегда означает атаку. Нестабильное сетевое соединение и/или немедленное удаление активной сессии может повлечь за собой подобное поведение.
С PHP 7.1.0 добавлена функция session_create_id() . Эта функция может быть полезна для создания идентификатора сессии с использованием идентификатора пользователя в качестве префикса для достижения большей управляемости. При её использовании крайне важно разрешать session.use_strict_mode. В противном случае недобросовестные пользователи смогут устанавливать поддельные идентификаторы сессий для других пользователей.
Замечание: В версиях PHP до 7.1.0 необходимо использовать CSPRNG , например, /dev/urandom или random_bytes() и функции хеширования для генерации нового идентификатора сессии. session_create_id() имеет встроенная функциональность обнаружения коллизий и генерирует идентификатор основываясь на INI-настройках. Использование session_create_id() является предпочтительной практикой.
Пересоздание идентификатора сессии
Использование session.use_strict_mode — это хорошо, но недостаточно. Разработчик также должен использовать session_regenerate_id() для обеспечения безопасности сессий.
Пересоздание идентификаторов сессий сильно уменьшает риск кражи сессии, соответственно надо на периодической основе запускать session_regenerate_id() . Например, пересоздавать идентификатор сессии каждые 15 минут для особо секретных данных. Даже если сессию украдут, она достаточно скоро станет истёкшей и попытка её использовать приведёт к ошибке истёкшей сессии.
Идентификатор сессии должен пересоздаваться при повышении привилегий пользователя, например при аутентификации. Функция session_regenerate_id() должна вызываться до записи авторизационной информации в $_SESSION . ( session_regenerate_id() сохраняет данные текущей сессии автоматически). Убедитесь, что только текущая сессия отмечена как авторизованная.
Разработчики НЕ ДОЛЖНЫ полагаться на механизм истечения срока действия идентификатора сессии с помощью session.gc_maxlifetime. Атакующие могут периодически получать доступ к сессии для предотвращения её срока действия и продолжать использовать идентификатор жертвы, включая аутентифицированные сессии.
Вместо этого, вы должны самостоятельно реализовать управление данными сессии базируясь на временной метке.
Внимание
Несмотря на то, что менеджер сессий может прозрачно управлять временными метками, эта функциональность не реализована. Данные старых сессий сохраняются до момента запуска сборщика мусора. В то же время, разработчики должны убедиться, что данные истёкших сессий удалены. Однако разработчики НЕ должны удалять данные активных сессий немедленно. Например, никогда не вызывайте session_regenerate_id(true); и session_destroy() совместно для активных сессий. Это может показаться противоречивым, но это обязательное требование.
session_regenerate_id() по умолчанию не удаляет старые сессии. Устаревшие авторизованные сессии могут быть доступны для использования. Разработчики должны пресечь любую возможность использования старых сессий кем-либо, запретив доступ к истёкшим сессиям самостоятельно, используя временные метки.
Внимание
Немедленное удаление активных сессий может повлечь нежелательные побочные эффекты. Сессия может прерваться из-за нестабильности сети или конкурентного доступа к сайту/приложению.
Потенциальный недобросовестный доступ будет невозможно отследить и проанализировать, если данные сессий будут немедленно удаляться.
Вместо немедленного удаления старых сессий вы должны сохранять их непродолжительное время, например, установив специальный флаг и время окончательного истечения сессии в $_SESSION , запретив кому-либо обращаться к этим данным.
Вы не должны запрещать доступ к старым сессиям сразу же после вызова session_regenerate_id() . Необходимо подождать несколько секунд для стабильных сетевых соединений и несколько минут для нестабильных, например для WiFi или мобильного интернета.
Если пользователь пытается получить доступ к истёкшей сессии, вы не должны его предоставлять. В этом случае рекомендуется удалять статус «авторизован» со всех активных сессий пользователя, поскольку это очень похоже на атаку.
session.use_only_cookies и правильное использование session_regenerate_id() могут привести к персональной DoS посредством установки неудаляемой cookie. Если такое происходит, то вы можете попросить пользователя удалить cookie и предупредить его о возможных проблемах с безопасностью. Атакующий может устанавливать вредные cookie через уязвимость в веб-приложении (то есть JavaScript-инъекция), уязвимость в браузерном плагине и т.д.
Внимание
Не недооценивайте риск DoS. session.use_strict_mode=On обязателен для общей безопасности идентификаторов сессий! Все сайты должны использовать session.use_strict_mode.
DoS (отказ в обслуживании) может произойти только тогда, когда аккаунт находится под атакой. Наиболее частая предпосылка для него — JavaScript-инъекция.
Удаление данных сессии
Данные истёкших сессий должны быть недоступны и удалены. Существующий механизм управления сессиями делает это не очень хорошо.
Данные истёкших сессий надо удалять так быстро, как только возможно. С другой стороны, данные активных сессий НЕ ДОЛЖНЫ удаляться сразу же. Для обеспечения этих противоречивых требований, вы ДОЛЖНЫ самостоятельно реализовать механизм контроля за истёкшими сессиями на базе временных меток.
Устанавливайте и управляйте временными метками жизни сессии через $_SESSION. Запрещайте доступ к данным истёкших сессий. Если обнаружена попытка доступа к данным устаревшей сессии, снимайте статус авторизации со всех активных сессий пользователя и вынуждайте его переавторизоваться. Доступ к данным истёкшей сессии может означать атаку. Для обеспечения такого поведения вы должны отслеживать все активные сессии пользователя.
Замечание: Доступ к истёкшей сессии может также произойти из-за нестабильного сетевого доступа и/или конкурентного доступа к приложению/сайту. Сервер может попытаться установить новый идентификатор сессии через cookie, но пакет «Set-Cookie» может не дойти до клиента из-за плохой связи. Одно соединение может вызвать пересоздание идентификатора посредством session_regenerate_id() , а другое, в то же время, может не получить нового идентификатора. Следовательно, вы должны запретить доступ к истёкшим сессиям чуть-чуть позже. То есть управление сессиями на базе временных меток является обязательным.
Короче говоря, не уничтожайте данные сессии ни с помощью session_regenerate_id() , ни session_destroy() , а используйте механизм доступа к сессии на базе временных меток. Пусть session_gc() сам удаляет старые сессии из хранилища.
Сессии и блокировки
По умолчанию данные сессии заблокированы, чтобы избежать состояния гонки. Блокировка обязательна для обеспечения консистентности данных сессии между запросами.
Однако блокировка может быть использована атакующим для организации DoS-атаки. Для уменьшения риска DoS с использованием блокировки сессий, минимизируйте их. Используйте блокировку «read only», когда сессию не нужно обновлять. Используйте опцию ‘read_and_close’ с session_start() . session_start([‘read_and_close’=>1]); Закрывайте сессию с помощью session_commit() сразу, как только вы закончили обновлять $_SESSION.
Текущий механизм управления сессиями не следит за изменениями $_SESSION, пока сессия неактивна. Это ваша зона ответственности, следить за тем, чтобы подобного не случалось.
Активные сессии
Разработчики должны следить за активными сессиями каждого пользователя и оповещать его, сколько есть активных сессий, с каких IP (и где географически), как долго они активны и т.д. PHP не сделает этого за вас. Вы должны это делать.
Есть несколько путей реализации. Вы можете хранить всю нужную информацию в специальной базе данных. Так что, когда сессия будет удалена сборщиком мусора, вы должны это отслеживать и соответственно обновлять свою базу данных.
Самый простой способ — использовать идентификатор пользователя в качестве префикса для идентификатора сессии и хранить всю требуемую информацию в $_SESSION. Многие базы данных умеют достаточно быстро выбирать строки по префиксу. Вы можете использовать session_regenerate_id() и session_create_id() для этого.
Внимание
Никогда в качестве префикса не используйте конфиденциальные данные. Если идентификатор пользователя конфиденциален, рассмотрите возможность использовать функцию hash_hmac() .
Внимание
Для подобной настройки требуется включение session.use_strict_mode. Убедитесь, что эта опция включена, иначе база данных активных сессий может быть скомпрометирована.
Управление сессиями на базе временных меток является обязательным для определения устаревших сессий. Если обнаружена попытка доступа к устаревшей сессии, необходимо сбросить флаги авторизации для всех активных сессий пользователя.
Сессии и автоматический вход
Разработчики НЕ ДОЛЖНЫ использовать долгоживущие сессии для реализации автоматического входа в систему, потому что это резко повышает вероятность кражи сессии. Автоматический вход в систему должен реализовываться разработчиком самостоятельно.
Устанавливайте безопасные хешированные одноразовые ключи в качестве ключей автологина с помощью setcookie() . Используйте безопасное хеширование, посильнее чем SHA-2, например SHA-256 или выше со случайными данными из random_bytes() или /dev/urandom .
Если пользователь не авторизован, проверьте, корректен ли одноразовый ключ автологина. Если ключ корректен, авторизуйте пользователя и установите ему новый одноразовый ключ. Ключ автологина обязательно должен быть одноразовым, то есть никогда не используйте его повторно, а всегда создавайте новый.
Ключ автологина — это очень долгоживущий ключ авторизации. Его надо защищать по максимуму. Используйте параметры path/httponly/secure/SameSite при установке cookie для его защиты. Никогда не передавайте ключ автологина, кроме случаев, когда это необходимо.
Разработчик должен реализовать функционал, который отключает автоматический вход в систему и удаляет ненужные «cookie», установленные для его реализации.
CSRF (Межсайтовая подделка запроса)
Сессии и авторизация не защищают от атак типа CSRF. Разработчики должны самостоятельно реализовывать защиту.
output_add_rewrite_var() может быть использована для защиты от CSRF. Читайте руководство для подробностей.
Замечание: До PHP 7.2.0 использовался один и тот же буфер вывода и INI-настройки для «trans sid». Так что использование output_add_rewrite_var() с PHP более ранних версий не рекомендуется.
Многие фреймворки поддерживают защиту от CSRF. Обратитесь к документации своего фреймворка для более подробной информации.
Начиная с PHP 7.3, для сессионной cookie можно установить атрибут SameSite. Это обеспечит дополнительную защиту против CSRF.
User Contributed Notes
There are no user contributed notes for this page.
- Безопасность сессий
- Базовые принципы управления сессиями
- INI-настройки безопасности сессий
Подводные камни использования сессий в PHP
Приветствую, уважаемое сообщество.
Прежде всего, хочу поблагодарить за очень полезный ресурс. Не раз находил здесь множество интересных идей и практических советов.
Цель этой статьи — осветить подводные камни использования сессий в PHP. Конечно, есть документация по PHP и масса примеров, и данная статья не претендует на полное руководство. Она призвана раскрыть некоторые ньюансы работы с сессиями и оградить разработчиков от ненужной траты времени.
Самым распространенным примером использования сессий является, конечно, авторизация пользователей. Начнем с самой базовой реализации, чтобы последовательно развивать ее по мере появления новых задач.
(В целях экономии места и времени ограничимся в примерах только самими функциями работы с сессиями, вместо того, чтобы строить здесь полноценное тестовое приложение с красивой иерархией классов, исчерпывающей обработкой ошибок и прочими правильными штуками).
function startSession() < // Если сессия уже была запущена, прекращаем выполнение и возвращаем TRUE // (параметр session.auto_start в файле настроек php.ini должен быть выключен - значение по умолчанию) if ( session_id() ) return true; else return session_start(); // Примечание: До версии 5.3.0 функция session_start()возвращала TRUE даже в случае ошибки. // Если вы используете версию ниже 5.3.0, выполняйте дополнительную проверку session_id() // после вызова session_start() >function destroySession() < if ( session_id() ) < // Если есть активная сессия, удаляем куки сессии, setcookie(session_name(), session_id(), time()-60*60*24); // и уничтожаем сессию session_unset(); session_destroy(); >>Примечание: Подразумевается, что базовые знания о сессиях PHP у читателя имеются, поэтому принцип работы функций session_start() и session_destroy() освещать здесь не будем. Задачи верстки формы входа и аутентификации пользователя не относятся к теме статьи, поэтому их мы также опустим. Напомню только, что для идентификации пользователя в каждом последующем запросе, нам необходимо в момент успешного входа сохранить в сессионной переменной (с именем userid, например) идентификатор пользователя, который будет доступен во всех последующих запросах в пределах жизни сессии. Также необходимо реализовать обработку результата нашей функции startSession(). Если функция вернула FALSE — отобразить в браузере форму входа. Если функция вернула TRUE, и сессионная переменная, содержащая идентификатор авторизованного пользователя (в нашем случае — userid), существует — отобразить страницу авторизованного пользователя (подробнее об обработке ошибок см. дополнение от 2013-06-07 в разделе о сессионных переменных).
Пока все понятно. Вопросы начинаются, когда требуется реализовать контроль отсутствия активности пользователя (session timeout), дать возможность одновременной работы в одном браузере нескольких пользователей, а также защитить сессии от несанкционированного использования. Об этом и пойдет речь ниже.
Контроль отсутствия активности пользователя встроенными средствами PHP
Первый вопрос, который часто возникает у разработчиков всевозможных консолей для пользователей — автоматическое завершение сеанса в случае отсутствия активности со стороны пользователя. Нет ничего проще, чем сделать это с помощью встроенных возможностей PHP. (Этот вариант не отличается особой надежностью и гибкостью, но рассмотрим его для полноты картины).
function startSession() < // Таймаут отсутствия активности пользователя (в секундах) $sessionLifetime = 300; if ( session_id() ) return true; // Устанавливаем время жизни куки ini_set('session.cookie_lifetime', $sessionLifetime); // Если таймаут отсутствия активности пользователя задан, устанавливаем время жизни сессии на сервере // Примечание: Для production-сервера рекомендуется предустановить эти параметры в файле php.ini if ( $sessionLifetime ) ini_set('session.gc_maxlifetime', $sessionLifetime); if ( session_start() ) < setcookie(session_name(), session_id(), time()+$sessionLifetime); return true; >else return false; >Немного пояснений. Как известно, PHP определяет, какую именно сессию нужно запустить, по имени куки, передаваемом браузером в заголовке запроса. Браузер же, в свою очередь, получает этот куки от сервера, куда помещает его функция session_start(). Если время жизни куки в браузере истекло, он не будет передан в запросе, а значит PHP не сможет определить, какую сессию нужно запустить, и расценит это как создание новой сессии. Параметр настроек PHP session.gc_maxlifetime, который устанавливается равным нашему таймауту отсутствия активности пользователя, задает время жизни PHP-сессии и контролируется сервером. Работает контроль времени жизни сессии следующим образом (здесь рассматривается пример хранилища сессий во временных файлах как самый распространенный и установленный по умолчанию в PHP вариант).
В момент создания новой сессии в каталоге, установленном как каталог для хранения сессий в параметре настроек PHP session.save_path, создается файл с именем sess_, где — идентификатор сессии. Далее, в каждом запросе, в момент запуска уже существующей сессии, PHP обновляет время модификации этого файла. Таким образом, в каждом следующем запросе PHP, путем разницы между текущим временем и временем последней модификации файла сессии, может определить, является ли сессия активной, или ее время жизни уже истекло. (Механизм удаления старых файлов сессий более подробно рассматривается в следующем разделе).
Примечание: Здесь следует отметить, что параметр session.gc_maxlifetime действует на все сессии в пределах одного сервера (точнее, в пределах одного главного процесса PHP). На практике это значит, что если на сервере работает несколько сайтов, и каждый из них имеет собственный таймаут отсутствия активности пользователей, то установка этого параметра на одном из сайтов приведет к его установке и для других сайтов. То же касается и shared-хостинга. Для избежания подобной ситуации используются отдельные каталоги сессий для каждого сайта в пределах одного сервера. Установка пути к каталогу сессий производится с помощью параметра session.save_path в файле настроек php.ini, или путем вызова функции ini_set(). После этого сессии каждого сайта будут храниться в отдельных каталогах, и параметр session.gc_maxlifetime, установленный на одном из сайтов, будет действовать только на его сессии. Мы не станем рассматривать этот случай подробно, тем более, что у нас в запасе есть более гибкий вариант контроля отсутствия активности пользователя.
Контроль отсутствия активности пользователя с помощью сессионных переменных
Казалось бы, предыдущий вариант при всей своей простоте (всего пару дополнительных строк кода) дает все, что нам нужно. Но что, если не каждый запрос можно расценивать как результат активности пользователя? Например, на странице установлен таймер, который периодически выполняет AJAX-запрос на получение обновлений от сервера. Такой запрос нельзя расценивать как активность пользователя, а значит автоматическое продление времени жизни сессии является не корректным в данном случае. Но мы знаем, что PHP обновляет время модификации файла сессии автоматически при каждом вызове функции session_start(), а значит любой запрос приведет к продлению времени жизни сессии, и таймаут отсутствия активности пользователя не наступит никогда. К тому же, последнее примечание из предыдущего раздела о тонкостях работы параметра session.gc_maxlifetime может показаться кому-то слишком запутанным и сложным в реализации.
Для решения этой проблемы откажемся от использования встроенных механизмов PHP и введем несколько новых сессионных переменных, которые позволят нам контролировать время отсутствия активности пользователей самостоятельно.
function startSession($isUserActivity=true) < $sessionLifetime = 300; if ( session_id() ) return true; // Устанавливаем время жизни куки до закрытия браузера (контролировать все будем на стороне сервера) ini_set('session.cookie_lifetime', 0); if ( ! session_start() ) return false; $t = time(); if ( $sessionLifetime ) < // Если таймаут отсутствия активности пользователя задан, // проверяем время, прошедшее с момента последней активности пользователя // (время последнего запроса, когда была обновлена сессионная переменная lastactivity) if ( isset($_SESSION['lastactivity']) && $t-$_SESSION['lastactivity'] >= $sessionLifetime ) < // Если время, прошедшее с момента последней активности пользователя, // больше таймаута отсутствия активности, значит сессия истекла, и нужно завершить сеанс destroySession(); return false; >else < // Если таймаут еще не наступил, // и если запрос пришел как результат активности пользователя, // обновляем переменную lastactivity значением текущего времени, // продлевая тем самым время сеанса еще на sessionLifetime секунд if ( $isUserActivity ) $_SESSION['lastactivity'] = $t; >> return true; >Подытожим. В каждом запросе мы проверяем, не достигнут ли таймаут с момента последней активности пользователя до текущего момента, и если он достигнут — уничтожаем сессию и прерываем выполнение функции, возвращая FALSE. Если же таймаут не достигнут, и в функцию передан параметр $isUserActivity со значением TRUE — обновляем время последней активности пользователя. Все, что нам остается сделать — это определять в вызывающем скрипте, является ли запрос результатом активности пользователя, и если нет — вызывать функцию startSession со значением параметра $isUserActivity, равным FALSE.
Обработка результата функции sessionStart()
В комментариях обратили внимание на то, что возврат FALSE не дает полного понимания причины ошибки, и это абсолютно справедливо. Я не стал публиковать здесь подробную обработку ошибок (объем статьи и так не маленький), поскольку это не относится напрямую к теме статьи. Но учитывая комментарии, внесу ясность.
Как видно, функция sessionStart может вернуть FALSE в двух случаях. Либо сессию не удалось запустить из-за каких-то внутренних ошибок сервера (например, неправильные настройки сессий в php.ini), либо время жизни сессии истекло. В первом случае мы должны перебросить пользователя на страницу с ошибкой о том, что есть проблемы на сервере, и формой обращения в службу поддержки. Во втором случае мы должны перевести пользователя на форму входа и вывести в ней соответствующее сообщение о том, что время сессии истекло. Для этого нам необходимо ввести коды ошибок и возвращать вместо FALSE соответствующий код, а в вызывающем методе проверять его и действовать соответствующим образом.
Теперь, даже если сессия на сервере по-прежнему существует, она будет уничтожена при первом же обращении к ней, если таймаут отсутствия активности пользователя истек. И это произойдет независимо от того, какое время жизни сессий установлено в глобальных настройках PHP.
Примечание: А что произойдет, если браузер был закрыт, и куки с именем сессии был автоматически уничтожен? Запрос к серверу при следующем открытии браузера не будет содержать куки сессии, и сервер не сможет открыть сессию и проверить таймаут отсутствия активности пользователя. Для нас это равносильно созданию новой сессии и никак не влияет на функционал и безопасность. Но возникает справедливый вопрос — а кто же тогда уничтожит старую сессию, если до сих пор ее уничтожали мы по истечении таймаута? Или она теперь будет висеть в каталоге сессий вечно? Для очистки старых сессий в PHP существует механизм под названием garbage collection. Он запускается в момент очередного запроса к серверу и чистит все старые сессии на основании даты последнего изменения файлов сессий. Но запуск механизма garbage collection происходит не при каждом запросе к серверу. Частота (а точнее, вероятность) запуска определяется двумя параметрами настроек session.gc_probability и session.gc_divisor. Результат от деления первого параметра на второй и есть вероятностью запуска механизма garbage collection. Таким образом, для того, чтобы механизм очистки сессий запускался при каждом запросе к севреру, эти параметры нужно установить в равные значения, например «1». Такой подход гарантирует чистоту каталога сессий, но, очевидно, является слишком накладным для сервера. Поэтому в production-системах по умолчанию устанавливается значение session.gc_divisor, равное 1000, что означает, что механизм garbage collection будет запускаться с вероятностью 1/1000. Если вы поэкспериментируете с этими настройками в своем файле php.ini, то сможете заметить, что в описанном выше случае, когда браузер закрывается и очищает все свои куки, в каталоге сессий какое-то время все еще остаются старые сессии. Но это не должно вас волновать, т.к. как уже было сказано, это ни коим образом не влияет на безопасность нашего механизма.
Предотвращение зависания скриптов из-за блокировки файла сессии
В комментариях подняли вопрос о зависании одновременно выполняющихся скриптов из-за блокировки файла сессии (как самый яркий вариант — long poll).
Для начала отмечу, что эта проблема напрямую не зависит от загруженности сервера или количества пользователей. Конечно, чем больше запросов, тем медленнее выполняются скрипты. Но это коссвенная зависимость. Проблема появляется только в пределах одной сессии, когда серверу приходит несколько запросов от имени одного пользователя (например, один из них long poll, а остальные — обычные запросы). Каждый запрос пытается получить доступ к одному и тому же файлу сессии, и если предыдущий запрос не разблокировал файл, то последующий будет висеть в ожидании.
Для сведения блокировки файлов сессий к минимуму настоятельно рекомендуется закрывать сессию путем вызова функции session_write_close() сразу после того, как выполнены все действия с сессионными переменными. На практике это означает, что не следует хранить в сессионных переменных все подряд и обращаться к ним на всем протяжении выполнения скрипта. А если и надо хранить в сессионных переменных какие-то рабочие данные, то считывать их сразу при старте сессии, сохранять в локальные переменные для последующего использования и закрывать сессию (имеется ввиду закрытие сессии с помощью функции session_write_close, а не уничтожение с помощью session_destroy).
В нашем примере это означает, что сразу после открытия сессии, проверки времени ее жизни и существования авторизованного пользователя, мы должны считать и сохранить все дополнительные необходимые приложению сессионные переменные (если такие существуют), после чего закрыть сессию с помощью вызова session_write_close() и продолжить выполнение скрипта, будь то long poll или обычный запрос.
Защита сессий от несанкционированного использования
Представим себе ситуацию. Один из ваших пользователей цепляет троян, который грабит куки браузера (в котором хранится наша сессия) и отправляет его на указанный email. Злоумышленник получает куки и использует его для подделки запроса от имени нашего авторизованного пользователя. Сервер успешно принимает и обрабатывает этот запрос, как если бы он пришел от авторизованного пользователя. Если не реализована дополнительная проверка IP-адреса, такая атака приведет к успешному взлому аккаунта пользователя со всеми вытекающими последствиями.
Почему это стало возможным? Очевидно, потому что имя и идентификатор сессии всегда одни и те же на все время жизни сессии, и если получить эти данные, то можно беспрепятственно слать запросы от имени другого пользователя (естественно, в пределах времени жизни этой сессии). Возможно, это не самый распространенный вид атак, но теоретически все выглядит вполне реализуемым, особенно учитывая, что подобному трояну даже не нужны права администратора, чтобы грабить куки браузера пользователя.
Как же можно защититься от атак подобного рода? Опять-таки, очевидно, ограничив время жизни идентификатора сессии и периодически изменяя идентификатор в пределах одной сессии. Мы можем также изменять и имя сессии, полностью удаляя старую и создавая новую сессию, копируя в нее все сессионные переменные из старой. Но на суть подхода это не влияет, поэтому для простоты ограничимся только идентификатором сессии.
Понятно, что чем меньше время жизни идентификатора сессии, тем меньше будет времени у злоумышленника, чтобы получить и применить куки для подделки запроса пользователя. В идеальном случае для каждого запроса должен использоваться новый идентификатор, что позволит свести к минимуму возможность использования чужой сессии. Но мы рассмотрим общий случай, когда время регенерации идентификатора сессии устанавливается произвольно.
(Опустим ту часть кода, которая уже рассмотрена).
function startSession($isUserActivity=true) < // Время жизни идентификатора сессии $idLifetime = 60; . if ( $idLifetime ) < // Если время жизни идентификатора сессии задано, // проверяем время, прошедшее с момента создания сессии или последней регенерации // (время последнего запроса, когда была обновлена сессионная переменная starttime) if ( isset($_SESSION['starttime']) ) < if ( $t-$_SESSION['starttime'] >= $idLifetime ) < // Время жизни идентификатора сессии истекло // Генерируем новый идентификатор session_regenerate_id(true); $_SESSION['starttime'] = $t; >> else < // Сюда мы попадаем, если сессия только что создана // Устанавливаем время генерации идентификатора сессии в текущее время $_SESSION['starttime'] = $t; >> return true; >Итак, при создании новой сессии (которое происходит в момент успешного входа пользователя), мы устанавливаем сессионную переменную starttime, хранящую для нас время последней генерации идентификатора сессии, в значение, равное текущему времени сервера. Далее в каждом запросе мы проверяем, не прошло ли достаточно времени (idLifetime) с момента последней генерации идентификатора, и если прошло — генерируем новый. Таким образом, если в течение установленного времени жизни идентификатора злоумышленник, получивший куки авторизованного пользователя, не успеет им воспользоваться, поддельный запрос будет расценен сервером как неавторизованный, и злоумышленник попадет на страницу входа.
Примечание: Новый идентификатор сессии попадает в куки браузера при вызове функции session_regenerate_id(), которая отправляет новый куки, аналогично функции session_start(), поэтому нам нет необходимости обновлять куки самостоятельно.
Если мы хотим максимально обезопасить наши сессии, достаточно установить время жизни идентификатора в единицу или же вообще вынести функцию session_regenerate_id() за скобки и убрать все проверки, что приведет к регенерации идентификатора в каждом запросе. (Я не проверял влияние такого подхода на быстродействие, и могу только сказать, что функция session_regenerate_id(true) выполняет по сути всего 4 действия: генерация нового идентификатора, создание заголовка с куки сессии, удаление старого и создание нового файла сессии).
Лирическое отступление: Если троян окажется настолько умным, что не будет отправлять куки злоумышленнику, а сам организует отправку заранее подготовленного поддельного запроса сразу при получении куки, описанный выше метод, скорее всего, не сможет защитить от подобной атаки, потому что между временем получения трояном куки и отправкой поддельного запроса практически не будет разницы, и велика вероятность, что в этот момент не произойдет регенерации идентификатора сессии.
Возможность одновременной работы в одном браузере от имени нескольких пользователей
Последняя задача, которую хотелось бы рассмотреть — возможность одновременной работы в одном браузере нескольких пользователей. Эта возможность особенно полезна на этапе тестирования, когда нужно эмулировать одновременную работу пользователей, и желательно делать это в своем любимом браузере, а не использовать весь доступный арсенал или открывать несколько экземпляров браузера в режиме «инкогнито».
В наших предыдущих примерах мы не задавали явно имя сессии, поэтому использовалось имя, установленное в PHP по умолчанию (PHPSESSID). Это значит, что все сессии, которые создавались нами до сих пор, отправляли браузеру куки под именем PHPSESSID. Очевидно, что если имя куки всегда одинаковое, то нет возможности в пределах одного браузера организовать две сессии с одинаковым именем. Но если бы мы для каждого пользователя использовали собственное имя сессии, то проблема была бы решена. Так и сделаем.
function startSession($isUserActivity=true, $prefix=null) < . if ( session_id() ) return true; // Если в параметрах передан префикс пользователя, // устанавливаем уникальное имя сессии, включающее этот префикс, // иначе устанавливаем общее для всех пользователей имя (например, MYPROJECT) session_name('MYPROJECT'.($prefix ? '_'.$prefix : '')); ini_set('session.cookie_lifetime', 0); if ( ! session_start() ) return false; . >Теперь осталось позаботиться о том, чтобы вызывающий скрипт передавал в функцию startSession() уникальный префикс для каждого пользователя. Это можно сделать, например, через передачу префикса в GET/POST параметрах каждого запроса или через дополнительный куки.
Заключение
В заключение приведу полный конечный код наших функций для работы с сессиями PHP, включающий все рассмотренные выше задачи.
function startSession($isUserActivity=true, $prefix=null) < $sessionLifetime = 300; $idLifetime = 60; if ( session_id() ) return true; session_name('MYPROJECT'.($prefix ? '_'.$prefix : '')); ini_set('session.cookie_lifetime', 0); if ( ! session_start() ) return false; $t = time(); if ( $sessionLifetime ) < if ( isset($_SESSION['lastactivity']) && $t-$_SESSION['lastactivity'] >= $sessionLifetime ) < destroySession(); return false; >else < if ( $isUserActivity ) $_SESSION['lastactivity'] = $t; >> if ( $idLifetime ) < if ( isset($_SESSION['starttime']) ) < if ( $t-$_SESSION['starttime'] >= $idLifetime ) < session_regenerate_id(true); $_SESSION['starttime'] = $t; >> else < $_SESSION['starttime'] = $t; >> return true; > function destroySession() < if ( session_id() ) < session_unset(); setcookie(session_name(), session_id(), time()-60*60*24); session_destroy(); >>Надеюсь, эта статья сэкономит немного времени тем, кто никогда особо не углублялся в механизм сессий, и даст достаточно понимания этого механизма тем, кто только начинает знакомиться с PHP.
- Веб-разработка
- PHP
- Программирование
Блокировка сессии в PHP

Технология сессии в PHP являются простым способом хранения информации для отдельно взятого пользователя сайта. Например: товары, добавленные в корзину магазина, настройки уведомлений и т.д. При первом запросе сайта к серверу, в браузере сохраняется в cookies уникальный идентификатор сессии пользователя. Затем идентификатор или связка идентификатора с IP адресом идентифицирует пользователя. Это может использоваться для сохранения состояния между запросами страниц. Идентификаторы сессий обычно отправляются браузеру через сессионный Cookie и используются для получения имеющихся данных сессии.
Сессии используют простую технологию: PHP будет либо получать данные существующей сессии, используя переданный идентификатор (обычно из сессионного cookie), или, если ничего не передавалось, будет создана новая сессия. PHP заполнит суперглобальную переменную $_SESSION сессионной информацией после того, как будет запущена сессия. Когда PHP завершает работу, он автоматически сериализует содержимое суперглобальной переменной $_SESSION и отправляет для сохранения, используя сессионный обработчик для записи сессии.
По умолчанию PHP использует внутренний обработчик files для сохранения сессий, который установлен в INI-переменной session.save_handler. Этот обработчик сохраняет данные на сервере в директории, указанной в конфигурационной директиве session.save_path.
Самый простой пример использования сессии, например, вывод количества обращений к странице для каждого пользователя:
else < $_SESSION['count']++; >echo $_SESSION['count'];Пример работы скрипта можно посмотреть по адресу https://beget.com/session_test.php.
Каким способом возможна блокировка сессий
На сайте php в секции описания работы сессий есть примечание (http://php.net/manual/ru/session.examples.basic.php):
Примечание:
Сессии, использующие файлы (по умолчанию в PHP), блокируют файл сессии сразу при открытии сессии функцией session_start() или косвенно при указании session.auto_start. После блокировки, ни один другой скрипт не может получить доступ к этому же файлу сессии, пока он не будет закрыт или при завершении скрипта или при вызове функции session_write_close().
Скорее всего это станет проблемой для сайтов, которые активно используют AJAX и делают несколько одновременных запросов. Простейшим путем решить эту проблему будет вызов функции session_write_close() сразу же как только все требуемые изменения в сессии будут сделаны, предпочтительно ближе к началу работы скрипта. Также можно использовать другой механизм сессии, который поддерживает конкурентный доступ.
В последнее время проблема блокирования сессий становится всё более частой. Отчасти это связано с усложнением сайтов и необходимостью производить больше вычислений на строне сервера, а так же с большим распространением AJAX. К сожалению, не всегда логика приложения, особенно если она сложная, позволяет эффективно ограничить время блокировки конкурирующих за сессию процессов. Ситуация усугубляется еще тем, что 3-5 подобных клиентов способны быстро забить зависшими и простаивающими в ожидании процессами PHP-воркеры, в результате чего сайт начнёт выдавать 5XX ошибку.
Самый простой пример блокировки сессий:
Если открыть этот файл сначала в первой вкладке, а потом во второй — вторая вкладка будет ждать, пока не доработает первая. То есть фактически вторая вкладка будет дожидаться, пока первая не освободит файл сессии (что занимает в конкретном случае 30 секунд). Данная проблема хорошо описана в блоге компании 1С-Битрикс на Habrahabr.
Какие варианты решения данной проблемы существуют
Для хранения сессий можно использовать БД, такие как MySQL или PostgreSQL (что не совсем правильно, учитывая возможности большинства БД и возможную скорость работы в данной задаче), Memcached (не гарантирует хранение сессии, возможно ее удаление) и Redis, который мы считаем оптимальным хранилищем. По скорости он не уступает Memcached, но при этом может гарантировать сохранность данных.
И самое главное приемущество Redis — при хранении в нем сессий они не блокируются.
В рамках нашей панели управления (cp.beget.com) можно включить хранение сессий в Redis для всех сайтов на аккаунте. Для этого необходимо перейти в раздел «Сайты», и далее отметить галочку — «Хранить сессии всех сайтов в Redis».


Дополнительные материалы
- http://php.net/manual/ru/session.examples.basic.php
- https://habrahabr.ru/company/bitrix/blog/179803/
- https://dev.1c-bitrix.ru/learning/course/?COURSE_ID=43&LESSON_ID=14026
Cессии¶
CakePHP предоставляет собственную оболочку и набор полезных функций поверх session расширения PHP. Cессии позволяют идентифицировать уникальных пользователей по запросам и хранить постоянные данные для определённых пользователей. В отличие от Cookies, данные сессии недоступны на стороне клиента. Использование $_SESSION вообще исключается в CakePHP, и вместо этого использование классов сеанса является предпочтительным.
Настройка сессии¶
Конфигурация сессии обычно определяется в /config/app.php . Доступны следующие варианты:
- Session.timeout — Число минут до того, как истечёт время CakePHP обработчика сессии.
- Session.defaults — Позволяет использовать встроенные конфигурации сессий по умолчанию в качестве базы для настройки сессии. Ниже приведены встроенные значения по умолчанию.
- Session.handler — Позволяет определить пользовательский обработчик сессии. Это используют сore database и обработчики кеш-сессии. См. ниже дополнительную информацию о обработчиках сессий.
- Session.ini — Позволяет вам установить дополнительные параметры сессии для вашей ini-конфигурации. Это в сочетании с Session.handler заменяет пользовательские функции обработки сеанса предыдущих версий.
- Session.cookie — Имя используемого файла cookie. По умолчанию используется значение „CAKEPHP“.
- Session.cookiePath — URL-адрес, для которого установлен сессионный файл cookie. Карты в конфигурацию session.cookie_path php.ini. По умолчанию используется базовый путь к приложению.
session.cookie_secure CakePHP по умолчанию установлено в true , когда ваше приложение находится по протоколу SSL. Если ваше приложение работает как с протоколами SSL, так и с протоколом, отличным от SSL, у вас могут возникнуть проблемы с потерями сеансов. Если вам нужен доступ к сеансу как для SSL, так и для доменов, не относящихся к SSL, вам необходимо отключить этот так:
Configure::write('Session', [ 'defaults' => 'php', 'ini' => [ 'session.cookie_secure' => false ] ]);
В пути к cookie сессии по умолчанию используется базовый путь приложения. Чтобы изменить это, вы можете использовать ini-значение session.cookie_path . Например, если вы хотите, чтобы ваша сессия сохранялась во всех поддоменах, вы можете сделать так:
Configure::write('Session', [ 'defaults' => 'php', 'ini' => [ 'session.cookie_path' => '/', 'session.cookie_domain' => '.yourdomain.com' ] ]);
По умолчанию PHP устанавливает, что cookie сессии истекает, как только браузер закрывается, независимо от настроенного значения Session.timeout . Тайм-аут cookie контролируется значением session.cookie_lifetime и может быть сконфигурирован с его использованием:
Configure::write('Session', [ 'defaults' => 'php', 'ini' => [ // Выполните инвалидацию cookie файла через 30 минут, // если за это время не посещена ни одна страница на сайте. 'session.cookie_lifetime' => 1800 ] ]);
Разница между Session.timeout и значением session.cookie_lifetime заключается в том, что последний полагается на то, что клиент говорит правду о cookie. Если вам требуется более строгая проверка тайм-аута, не полагайтесь на то, что сообщает клиент, а используйте Session.timeout .
Обратите внимание, что Session.timeout соответствует общему времени бездействия для пользователя (т.е. времени без посещения любой страницы, где используется сессия), и не ограничивает общее количество минут, на которые пользователь может оставаться на сайт.
Встроенные обработчики сессий и конфигурации¶
CakePHP поставляется с несколькими встроенными конфигурациями сессий. Вы можете либо использовать их в качестве основы для своей конфигурации сессии, либо создать полностью настраиваемое решение. Чтобы использовать значения по умолчанию, просто установите ключ „defaults“ на имя используемого по умолчанию. Затем вы можете переопределить любой дополнительный параметр, объявив его в конфигурации вашей сессии:
Configure::write('Session', [ 'defaults' => 'php' ]);
Вышеизложенное будет использовать встроенную „php“ конфигурацию сессии. Вы можете изменить её часть или всё, выполнив следующие действия:
Configure::write('Session', [ 'defaults' => 'php', 'cookie' => 'my_app', 'timeout' => 4320 // 3 дня ]);
Вышеупомянутое переопределяет тайм-аут и имя файла cookie для конфигурации „php“ сессии. Встроенные конфигурации:
- php — Сохраняет сессии со стандартными настройками в файле php.ini.
- cake — Сохраняет сессии как файлы внутри tmp/sessions . Это хороший вариант, когда на хостах не разрешено писать за пределами собственного домашнего каталога.
- database — Используйте встроенные сеансы базы данных. Смотрите ниже для получения дополнительной информации.
- cache — Используйте встроенный кэш сессий. Смотрите ниже для получения дополнительной информации.
Обработчики сессий¶
Обработчики сессий также могут быть определены в массиве конфигурации сессии. Определив ключ конфигурации „handler.engine“, вы можете назвать имя класса или предоставить экземпляр обработчика. Класс/объект должен реализовывать собственный PHP SessionHandlerInterface . Внедрение этого интерфейса позволит Session автоматически отображать методы для обработчика. Оба основных обработчика кэша сессии и базы данных используют этот метод для сохранения сессий. Дополнительные настройки для обработчика должны быть помещены внутри массива обработчиков. Затем вы можете прочитать эти значения изнутри вашего обработчика:
'Session' => [ 'handler' => [ 'engine' => 'DatabaseSession', 'model' => 'CustomSessions' ] ]
Вышеописанное показывает, как можно настроить обработчик сессии базы данных с помощью модели приложения. При использовании имён классов в качестве обработчика, CakePHP ожидает, что ваш класс будет найден в пространстве имён Network\Session . Например, если у вас есть класс AppSessionHandler , файл должен быть src/Network/Session/AppSessionHandler.php, а имя класса должно быть App\Network\Session\AppSessionHandler . Вы также можете использовать обработчики сессий изнутри плагинов, установив двигатель в MyPlugin.PluginSessionHandler .
База данных сессий¶
Если вам нужно использовать базу данных для хранения данных сессии, это можно настроить следующим образом:
'Session' => [ 'defaults' => 'database' ]
Для этой конфигурации требуется таблица базы данных, имеющая эту схему:
CREATE TABLE `sessions` ( `id` char(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, `created` datetime DEFAULT CURRENT_TIMESTAMP, -- Optional `modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- Optional `data` blob DEFAULT NULL, -- for PostgreSQL use bytea instead of blob `expires` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Копию схемы для таблицы сессий можно найти в скелете приложения в config/schema/sessions.sql .
Вы также можете использовать свой собственный класс Table для обработки сохранения сессий:
'Session' => [ 'defaults' => 'database', 'handler' => [ 'engine' => 'DatabaseSession', 'model' => 'CustomSessions' ] ]
Вышеприведённое будет означать, что Session использует встроенные значения „database“ по умолчанию и указывает, что таблица, называемая CustomSessions , будет делегатом для сохранения информации о сессии в базе данных.
Кеширование сессий¶
Класс Cache также может использоваться для хранения сессий. Это позволяет хранить сессии в кэше, таком как APC, Memcached или XCache. Есть некоторые оговорки, связанные с использованием кэша сессий, поскольку если вы исчерпаете пространство кэша, сессии начнут истекать по мере удаления записей из кэша.
Чтобы использовать сессии на основе кэша, вы можете настроить конфигурацию сессии так:
Configure::write('Session', [ 'defaults' => 'cache', 'handler' => [ 'config' => 'session' ] ]);
Это позволит настроить Session для использования класса CacheSession в качестве делегата для сохранения сессий. Вы можете использовать ключ конфигурации, в котором используется конфигурация кэша. Конфигурация кэша по умолчанию — ‘default’ .
Настройка ini директив¶
Встроенные по умолчанию настройки пытаются обеспечить общую базу для настройки сессий. Возможно, вам потребуется также настроить определенные флаги ini. CakePHP предоставляет возможность настраивать параметры ini как для стандартных конфигураций, так и для пользовательских. Ключ ini в настройках сессии позволяет указать индивидуальные значения конфигурации. Например, вы можете использовать его для управления настройками типа session.gc_divisor :
Configure::write('Session', [ 'defaults' => 'php', 'ini' => [ 'session.cookie_name' => 'MyCookie', 'session.cookie_lifetime' => 1800, // Валидно 30 минут 'session.gc_divisor' => 1000, 'session.cookie_httponly' => true ] ]);
Создание пользовательского обработчика сессии¶
Создание пользовательского обработчика сессии прямо в CakePHP. В этом примере мы создадим обработчик сессии, который хранит сессии как в кэше (APC), так и в базе данных. Это даёт нам лучшее из быстрого ввода-вывода APC, не беспокоясь о том, что сессии испаряются, когда кэш заполняется.
Сначала нам нужно создать наш собственный класс и поместить его в src/Network/Session/ComboSession.php. Класс должен выглядеть примерно так:
namespace App\Network\Session; use Cake\Cache\Cache; use Cake\Core\Configure; use Cake\Network\Session\DatabaseSession; class ComboSession extends DatabaseSession public $cacheKey; public function __construct() $this->cacheKey = Configure::read('Session.handler.cache'); parent::__construct(); > // Чтение данных сессии. public function read($id) $result = Cache::read($id, $this->cacheKey); if ($result) return $result; > return parent::read($id); > // Запись данных в сессию. public function write($id, $data) Cache::write($id, $data, $this->cacheKey); return parent::write($id, $data); > // Уничтожение сессии. public function destroy($id) Cache::delete($id, $this->cacheKey); return parent::destroy($id); > // Удаление истёкших сессий. public function gc($expires = null) return Cache::gc($this->cacheKey) && parent::gc($expires); > >
Наш класс расширяет встроенную DatabaseSession , поэтому нам не нужно дублировать всю её логику и поведение. Мы завершаем каждую операцию с помощью Cake\Cache\Cache . Это позволяет нам получать сессии из быстрого кэша и не беспокоиться о том, что происходит, когда мы заполняем кэш. Использование этого обработчика сессии также легко. В вашем config/app.php сделайте блок сессии следующим:
'Session' => [ 'defaults' => 'database', 'handler' => [ 'engine' => 'ComboSession', 'model' => 'Session', 'cache' => 'apc' ] ], // Не забудьте добавить конфигурацию кэша Apc 'Cache' => [ 'apc' => ['engine' => 'Apc'] ]
Теперь наше приложение начнёт использовать наш специальный обработчик сессии для чтения и записи данных сессии.
Доступ к объекту сессии¶
Вы можете получить доступ к данным сессии в любом месте, где у вас есть доступ к объекту запроса. Это означает, что объект сессии доступен из:
- Controllers
- Views
- Helpers
- Cells
- Components
В дополнение к основному объекту сессии вы также можете использовать Cake\View\Helper\SessionHelper для взаимодействия с сессией в ваших представлениях. Основным примером использования сессии будет:
$name = $this->request->session()->read('User.name'); // Если вы получаете доступ к сессии несколько раз, вам, // вероятно, понадобится локальная переменная. $session = $this->request->session(); $name = $session->read('User.name');
Чтение и запись данных сессии¶
Session:: read ( $key ) ¶
Вы можете читать значения из сессии, используя Hash::extract() совместимый синтаксис:
$session->read('Config.language');
Session:: write ( $key , $value ) ¶
$key должна быть разделенна точками пути, который вы хотите записать в $value :
$session->write('Config.language', 'en');
Вы также можете указать один или несколько хэшей, например:
$session->write([ 'Config.theme' => 'blue', 'Config.language' => 'en', ]);
Session:: delete ( $key ) ¶
Когда вам нужно удалить данные из сессии, вы можете использовать delete() :
$session->delete('Some.value');
static Session:: consume ( $key ) ¶
Когда вам нужно читать и удалять данные из сессии, вы можете использовать consume() :
$session->consume('Some.value');
Session:: check ( $key ) ¶
Если вы хотите увидеть, существуют ли определённые данные в сессии, вы можете использовать check() :
if ($session->check('Config.language')) // Config.language существует и не является нулевым. >
Уничтожение сессии¶
Session:: destroy ( ) ¶
Уничтожение сессии полезно, когда пользователи выходят из системы. Чтобы уничтожить сессию, используйте метод destroy() :
$session->destroy();
Уничтожение сессии удалит все серверные данные из сессии, но не удалит куки-файл сессии.
Возобновление идентификаторов сессии¶
Session:: renew ( ) ¶
В то время как AuthComponent автоматически обновляет идентификатор сессии при входе в систему и выходе из системы, вам может потребоваться возобновить идентификатор сессии вручную. Для этого используйте метод renew() :
$session->renew();
Flash-сообщения¶
Flash-сообщения — это небольшие сообщения, отображаемые конечным пользователям один раз. Они часто используются для представления сообщений об ошибках или подтверждения того, что действия прошли успешно.
Чтобы установить и отобразить флэш-сообщения, вы должны использовать Флэш и Мгновенные сообщения
- Первое знакомство с CakePHP
- Инструкция по началу работы
- Руководство по миграции 3.x
- Руководства и примеры
- Сотрудничество
- Установка
- Конфигурация
- Маршрутизация
- Объекты запроса и ответа
- Промежуточное ПО
- Контроллеры
- Представления
- Доступ к Базе Данных и ORM
- Аутентификация
- Кэширование
- Shells, Tasks & Console Tools
- Debugging
- Deployment
- Error & Exception Handling
- Events System
- Internationalization & Localization
- Logging
- Формы без Модели
- Пагинация
- Плагины
- REST
- Безопасность
- Cессии
- Testing
- Validation
