Конфігурація сесій та обробники збережень

Дата оновлення перекладу 2022-12-12

Конфігурація сесій та обробники збережень

Цей розділ розповідає про те, як конфігурувати управління сесіями та налаштовувати його під ваші потреби. Ця документація охоплюе обробники збережень, які зберігають та вилучають дані сесії та конфігурацію поведінки сесії.

Обробники збережень

Робочий процес PHP-сесії має 6 можливих операцій, які можуть статися. Нормальна сесія слідує open, read, write та close, з можливими destroy та gc (скидання сміття, яке призведе до закінчення строку дії всіх старих сесій: gc викликається рандомно у відповідності до конфігурації PHP, і у випадку його виклику, він активізується після операції open). Ви можете прочитати більше про це тут php.net/session.customhandler

Оригінальні PHP-обробники збережень

Так звані оригінальни обробники - це обробники збережень, які або компілюються в PHP, або надаються PHP-розширеннями, на кшталт PHP-SQlite, PHP-Memcached і т.д.

Всі оригінальні обробники збережень внутрішні в PHP, і тому не мають публічного API. Вони мають бути сконфігуровані директивами php.ini, зазвичай session.save_path, і потенційно іншими директивами, пов'язаними з драйверами. Конкретні деталі можна знайти в блоці документів методу setOptions() кожного класу. Наприклад, наданий розширенням Memcached, може бути знайдений тут php.net.

В той час, як оригінальні обробники можуть бути активовані напряму з використанням ini_set('session.save_handler', $name);, Symfony надає зручний спосіб активувати їх так само, як активуються користувацькі обробники.

Symfony надає дравери для наступного обробника збережень в якості прикладу:

Приклад використання:

1
2
3
4
5
6
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

$sessionStorage = new NativeSessionStorage([], new NativeFileSessionHandler());
$session = new Session($sessionStorage);

Note

За виключенням обробника files, який вбудований в PHP та доступний завжди, доступність інших обробників залежить від активних під час середовища виконання PHP-розширень.

Note

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

Користувацькі обробники збережень

Користуваьцкі обробники - це ті, які повністю замінюють вбудовані в PHP обробники збереження сесій, та надають шість функцій зворотнього виклику, які PHP викликає внутрішньо в різні моменти робочого процесу сесії.

Компонент Symfony HttpFoundation надає декілька за замовчуванням, і вони можуть служити прикладом у випадку, якщо ви захочете написати власні.

Приклад використання:

1
2
3
4
5
6
7
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

$pdo = new \PDO(...);
$sessionStorage = new NativeSessionStorage([], new PdoSessionHandler($pdo));
$session = new Session($sessionStorage);

Міграція між обробниками збережень

Якщо ваш доадток змінює те, як зберігаються сесії, використовуйте MigratingSessionHandler, щоб мігрувати між старими та новими обробниками збережень, не втрачаючи дані сеісії.

Ось рекомендований процес роботи міграції:

  1. Перемкніться на мігруючий обробник, в той час, як ваш новий обробник буде доступний лише для запису. Старий обробник поводить себе як зазвичай, а сесії записуються в новий:

    1
    $sessionStorage = new MigratingSessionHandler($oldSessionStorage, $newSessionStorage);
  2. Після етапу збору сміття в вашій сесії, верифікуйте вірність даних в новому обробнику.
  3. Оновіть мігруючий обробник, щоб він використовував старий лише для запису, щоб тепер сесії зчитувалися з нового обробнику. Цей крок дозволяє спрощені відкати:

    1
    $sessionStorage = new MigratingSessionHandler($newSessionStorage, $oldSessionStorage);
  4. Після верифікації того, що сесії в вашому додатку працюють, перейдіть з мігруючого обробника на новий обробник.

Конфігурація PHP-сесій

NativeSessionStorage може сконфігурувати більшість директив конфігурації php.ini, які задокументовані в php.net/session.configuration.

Щоб сконфігурувати ці налаштування, передайте ключі (опустивши початкову частину ключа session.) в якості масиву ключ-значення аргументу конструктору $options. Або встановіть їх через метод setOptions().

Заради ясності, деякі ключові опції пояснюються в цій документації.

Час життя куки сесії

З міркувань безпеки, токени сесії зазвичай рекомендується відправляти в куки сесії. Ви можете сконфігурувати час життя куки сесій, вказавши час життя (в секундах), використовуючи ключ cookie_lifetime в аргументі конструктору $options в NativeSessionStorage.

Налаштування cookie_lifetime, як 0, призведе до того, що куки буде жити тільки поки браузер буде відкрито. Зазвичай, cookie_lifetime встановлюється в достатньо великій кількості днів, тижнів або місяці. Нерідко також час життя куки встановлюється як рік або більше, в залежності від додатку.

Так як куки сесій - це всього лише токени клієнтської сторони, вони менш важливі в контролюванні дрібних деталей ваших налаштувань безпеки, які за замовчуванням можуть бути безпечно контрольовані лище зі сторони серверу.

Note

Налаштування cookie_lifetime - це кількість секунд, яку має жити куки, а не часова відмітка Unix. Результуючий куки сессії буде мати відмітку закінчення терміну дії time() + cookie_lifetime, де час - токен від серверу.

Конфігурація збору сміття

Коли сесія відкривається, PHP рандомно викликає обробник gc у відповідності з ймовірністю, встановленій session.gc_probability / session.gc_divisor. Наприклад, якщо вони встановлені, як 5/100 відповідно, це буде означати йомвірність 5%. Таким же чином, 3/4 буде означати 3 з 4 шансів виклику, тобто 75%.

Якщо активується обробник збору сміття, PHP передасть значення, збережене в директиві php.ini session.gc_maxlifetime. Значення в цьому контексті в тому, що будь-яка збережена сесія, яка була збережена раніше, ніж gc_maxlifetime, має бути видалена. Це дозвляє утилізувати записи в залежності від часу простою.

Однак, деякі ОС (наприклад, Debian) проводять власну обробку сесій, та встановлюють змінну session.gc_probability, як 0, щоб зупинити PHP від збору сміття. Тому тепер Symfony перезаписує це значення, як 1.

Якщо ви хочете використовувати оригінальне значення, встановлене в вашому php.ini, додайте наступну конфігурацію:

  • YAML
  • XML
  • PHP
1
2
3
4
# config/packages/framework.yaml
framework:
    session:
        gc_probability: null

Ви можете сконфігурувати ці налаштування, передавши gc_probability, gc_divisor та gc_maxlifetime в масиві консруктору NativeSessionStorage або методу setOptions().

Час життя сесії

Коли створюється нова сесія, це означає, що Symfony випускає новий кукі сесії клієнту, куки буде відмічений часом закінчення терміну дії. Він розраховується шляхом додавання значення конфігурації прогону PHP в session.cookie_lifetime з поточним часом серверу.

Note

PHP випускатиме кукі лише один раз. Очікується, що клієнт буде зберігати цей кукі весь час життя. Новий кукі буде випущений лише після руйнації сесії, видалення кукі браузеру або регенарції ID сесії, з використанням методів migrate() або invalidate() класу Session.

Початковий час життя кукі може бути встановлений шляхом конфігурації NativeSessionStorage, з використанням методу setOptions(['cookie_lifetime' => 1234]).

Note

Час життя кукі 0 означає, що строк дії кукі закінчується після закриття браузеру.

Час простою сесії/Постійне з'єднання

Часто виникають обставини, в яких ви можете захотіти захистити або мінімізувати неавторизоване використання сесії, коли користувач відходить від терміналу, залишаючись в системі, знищивши сесію після певного часу простою. Наприклад, для банківських додатків, розповсюджено виконувати вихід користувача через 5-10 хвилин бездіяльності. Встановлення часу життя куки тут неправильне, так як воно може бути змінене клієнтом, тому нам необхідно встановити строк закінчення терміну дії на стороні серверу. Найпростішим способом релазіації цього є збір сміття, з достатньо високою частотою. cookie_lifetime буде встановлено в достатньо високому значенні, а збір сміття gc_maxlifetime буде встановлено для знищення сесій після будь-якого бажаного часу простою.

Інший варіант - конкретно перевіряти, чи не закінчилася сесія після її початку. Сесія може бути зруйнована за вимогою. Цей метод обробки може дозволити інтеграцію закінчення строку дії сесії в досвід користувача, наприклад, шляхом відображння повідомлення.

Symfony записує базові метадані з кожної сесії, щоб надати вам повну свободу в цій сфері.

Лімітування кешу сесії

Щоб уникнути відображення користувачам застарілих даних, часто джерела, включені сесією, відправляються з заголовками, що відключають кешування. Для цих цілей PHP-сесії мають опцію sessions.cache_limiter, яка визначає, які заголовки будуть відправлені з відповіддю при запуску сесії.

При побудові, NativeSessionStorage встановлює цю глобальну опцію, як "" (не відправляти заголовки) у випадку, якщо розробник хоче використовувати об'єкт Response для управління заголовками відповідей.

Caution

Якщо ви покладаєтесь на PHP-сесії в обробці HTTP-кешування, ви маєте вручну встановити опцію cache_limiter в NativeSessionStorage, як не порожнє значення.

Наприклад, ви можете встановити її як значення PHP за замочуванням, під час побудови:

Приклад використання:

1
2
3
4
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;

$options['cache_limiter'] = session_cache_limiter();
$sessionStorage = new NativeSessionStorage($options);

Метадані сесії

Сесії декодуються деякими базовими метаданими для включення ретельного контролю налаштувань безпеки. Об'єкт сесії має гетер для метаданих, getMetadataBag(), який відображає екземпляр MetadataBag:

1
2
$session->getMetadataBag()->getCreated();
$session->getMetadataBag()->getLastUsed();

Обидва методи повертають часову відмітку Unix (що відноситься до серверу).

Ці метадані можуть бути використані для чіткого закінчення сесії при доступі, наприклад:

1
2
3
4
5
$session->start();
if (time() - $session->getMetadataBag()->getLastUsed() > $maxIdleTime) {
    $session->invalidate();
    throw new SessionExpired(); // перенаправление на страницу истекшей сессии
}

Також можливо сказати, який cookie_lifetime був встановлений для конкретного кукі, якщо прочитати метод getLifetime():

1
$session->getMetadataBag()->getLifetime();

Час закінчення строку дії кукі може бути визначений шляхом додавання створеної часової відмітки та часу життя.