Де зберігаються сесії php. PHP сесії під скальпелем
В Інтернеті можна знайти тисячі туторіали про те, що таке сесії, для чого вони потрібні і як з ними працювати. Але, на жаль, прочитавши їх, все одно залишається безліч питань. На мій погляд, найпростіший спосіб розібратися в усьому - це подивитися, як працюють сесії зсередини. Тобто вивчити логи обміну браузера і веб-сервера, а також подивитися, які дані зберігаються на стороні клієнта і на стороні сервера.
Після цього багато моментів стають куди більш зрозумілими, а сам механізм роботи - більш прозорим.
Роботу сесій будемо вивчати на наступному стандартному скрипті:
Він працює таким чином:
Блок 1. Функція session_start () створює нову сесію або завантажує стару, використовуючи унікальний ідентифікатор сесії PHPSESSID.
Блок 2. Якщо вдалося відновити сесію, то значення $ _SESSION [ "views"] збільшується на одиницю. Якщо немає - инициализируется одиницею.
За ідеєю, якщо в браузері включена підтримка кук, механізм повинен працювати і при кожному оновленні сторінки значення лічильника буде збільшуватися на одиницю.
Щоб вперше отримати скрипта
заголовки запиту
GET / HTTP / 1.1 Host: firingrange.local User-Agent: Mozilla / 5.0 (Windows NT 5.1; rv: 6.0.2) Gecko / 20100101 Firefox / 6.0.2 Accept: text / html, application / xhtml + xml, application / xml; q \u003d 0.9, * / *; q \u003d 0.8 Accept-Language: ru-ru, ru; q \u003d 0.8, en-us; q \u003d 0.5, en; q \u003d 0.3 Accept-Encoding: gzip, deflate Accept-Charset : windows-1251, utf-8; q \u003d 0.7, *; q \u003d 0.7 Connection: keep-alive Cache-Control: max-age \u003d 0заголовки відповіді
HTTP / 1.1 200 OK Date: Thu, 29 Sep 2011 20:36:15 GMT Server: Apache / 2.2.13 (Win32) PHP / 5.2.10 X-Powered-By: PHP / 5.2.10 Set-Cookie: PHPSESSID \u003d k33en6ccgcia7125mitj5te4u6; path \u003d / Expires: Thu, 19 Nov одна тисяча дев'ятсот вісімдесят одна 8:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check \u003d 0, pre-check \u003d 0 Pragma: no-cache Content-Length: 58 Keep-Alive: timeout \u003d 5, max \u003d 100 Connection: Keep-Alive Content-Type: text / htmlкоментар
У вихідному запиті браузер не ідентифікував себе ніяким чином, тому механізм сесій PHP згенерував новий унікальний ідентифікатор сесії і скомандував браузеру створити куку, в якій буде зберігатися цей самий ідентифікатор.
сторона сервера
В результаті роботи скрипта на стороні сервера створюється файл sess_k33en6ccgcia7125mitj5te4u6 такого змісту:
сторона клієнта
На стороні клієнта створюється кука PHPSESSID, в якій зберігається значення унікального ідентифікатора сесії.
Примітка. при настройках PHP за замовчуванням, час життя куки PHPSESSID - до закриття браузера. Тобто як тільки браузер буде закритий, кука буде вилучена, а відповідно буде втрачена сесія. Час життя куки PHPSESSID можна змінювати, варіюючи значення session.cookie_lifetime.
Результат роботи скрипта
Друга завантаження скрипта
заголовки запиту
GET / HTTP / 1.1 Host: firingrange.local User-Agent: Mozilla / 5.0 (Windows NT 5.1; rv: 6.0.2) Gecko / 20100101 Firefox / 6.0.2 Accept: text / html, application / xhtml + xml, application / xml; q \u003d 0.9, * / *; q \u003d 0.8 Accept-Language: ru-ru, ru; q \u003d 0.8, en-us; q \u003d 0.5, en; q \u003d 0.3 Accept-Encoding: gzip, deflate Accept-Charset: windows-1251, utf-8; q \u003d 0.7, *; q \u003d 0.7 Connection: keep-alive Cookie: PHPSESSID \u003d k33en6ccgcia7125mitj5te4u6 Cache-Control: max-age \u003d 0заголовки відповіді
HTTP / 1.1 200 OK Date: Thu, 29 Sep 2011 20:49:41 GMT Server: Apache / 2.2.13 (Win32) PHP / 5.2.10 X-Powered-By: PHP / 5.2.10 Expires: Thu, 19 Nov 1981 8:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check \u003d 0, pre-check \u003d 0 Pragma: no-cache Content-Length: 58 Keep-Alive: timeout \u003d 5, max \u003d 100 Connection: Keep-Alive Content-Type: text / htmlкоментар
Браузер відправляє веб-сервера куку PHPSESSID, використовуючи яку PHP инициализирует масив $ _SESSION значеннями з файлу sess_k33en6ccgcia7125mitj5te4u6. Відповідно, в блоці 2 відпрацьовує гілка IF (пряма).
сторона сервера
В результаті роботи скрипта вміст файлу sess_k33en6ccgcia7125mitj5te4u6 змінюється:
сторона клієнта
На стороні клієнта нічого не змінюється.
Результат роботи скрипта
Що далі?
Наступні завантаження сторінки до закриття браузера будуть працювати за аналогією з тим, як працювала друга завантаження скрипта.
Оскільки час життя куки було обмежено поточної сесією браузера, то після його закриття унікальний ідентифікатор сесії буде втрачено і при перезапуску процес піде по новій.
Проте можна повернутися до збереженої сесії, якщо явно вказати PHPSESSID як параметр скрипта:
Повернення до сесії досить умовне, тому що в результаті роботи скрипта в даному випадку Кука не створюється. Заголовки відповіді сервера:
HTTP / 1.1 200 OK Date: Thu, 29 Sep 2011 21:01:52 GMT Server: Apache / 2.2.13 (Win32) PHP / 5.2.10 X-Powered-By: PHP / 5.2.10 Expires: Thu, 19 Nov 1981 8:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check \u003d 0, pre-check \u003d 0 Pragma: no-cache Content-Length: 58 Keep-Alive: timeout \u003d 5, max \u003d 100 Connection: Keep-Alive Content-Type: text / html
Тобто для підтримки роботи саме з цією сесією до всіх посилань доведеться приписувати? PHPSESSID \u003d k33en6ccgcia7125mitj5te4u6.
Примітка. Можна вказати PHP, щоб унікальний ідентифікатор сесії передавався тільки через куку. Для цього потрібно встановити session.use_only_cookies в значення 1. У цьому випадку трюк, продемонстрований вище, не пройде.
Якщо куки в браузері відключені, то можна передавати ідентифікатор сесії через параметри, як ми робили вище. Причому в PHP є механізм, який буде сам дописувати потрібний параметр в посилання і додавати приховані поля в форми. Принцип роботи такий самий, як і з куками, тому не будемо розбирати цей випадок окремо.
Невеликий запитальник (FAQ)
Де фізично зберігаються дані сесій?
Дані сесій зберігаються на сервері. За умовчанням вони записуються в файли, але можна поставити свій власний механізм зберігання даних сесій (наприклад з використанням бази даних). Якщо хочете подробиць, дивіться функцію session_set_save_handler.
Хто генерує унікальний ідентифікатор сесії?
Унікальний ідентифікатор сесії (PHPSESSID) генерує сервер.
Чи можна написати власний механізм сесій?
Так, це цілком можливо. Як бачите, PHP не використовує нічого надприродного - ідентифікатор зберігається між запитами за допомогою кук, дані сесій зберігаються в файлах на сервері.
Наприклад, власний механізм роботи з сесіями є в популярному фреймворку CodeIgniter.
Наскільки безпечний механізм сесій?
Сесія ідентифікується тільки за допомогою унікального ідентифікатора сесії, тому в загальному випадку зловмисникові досить вкрасти його, щоб заплутати сервер. Візьмемо тестовий скрипт, який ми використовували вище. Якщо звернення до нього буде з іншого IP (по відношенню до створив сесію), але PHPSESSID передаватиметься той же самий, то сесія буде успішно відновлена \u200b\u200bі лічильник буде збільшуватися з попереднього збереженого значення.
забезпечувати додатковий захист доведеться вам самим. наприклад:
- Можна зберігати в даних сесії IP і User-Agent клієнта (буде зберігатися на стороні сервера), а потім при кожному зверненні перевіряти, що актуальні значення збігаються з збереженими. В даному випадку доводиться шукати компроміс між безпекою та зручністю роботи користувача.
Наприклад, якщо у користувача динамічний IP і ви використовуєте сесії для підтримки авторизації, але при цьому перевіряєте збіг IP, то при кожній зміні адреси користувачеві доведеться заново вводити логін і пароль.
Точно також рядок User-Agent може змінюватися при оновленні версії браузера або при установці деяких плагінів.
- Одним з рекомендованих механізмів захисту сесій є повторна генерація ідентифікатора при кожному зверненні до скрипту (див. Функцію session_regenerate_id). Подивитися скрипт і алгоритм роботи в розрізі можна нижче.
Примітка.Якщо вірити обговорення на офіційному сайті, то при повторній генерації ідентифікатора можуть виникнути проблеми з паралельним доступом до даних.
Робота сесій з повторною генерацією ідентифікатора в розрізі
скрипт
// блок 1
session_start ();
if(isset($ _SESSION [ "initiated"]))
session_regenerate_id ();
else
$ _SESSION [ "initiated"] \u003d true;
// блок 2
if(isset($ _SESSION [ "views"]))
$ _SESSION [ "views"] ++;
else
$ _SESSION [ "views"] \u003d 1;
// блок 3
echo"
<
body>
Кількість переглядів: ". $ _SESSION [" views "]."