::: PHP.com.ua - учимся вместе. ::: ::: PHP.com.ua - учимся вместе. :::



 
   - Вакансия PHP-программист, Днепропетровск...
  - Проблема с передачей переменной в PHP ск...
  - Как хранить конфигурацию cms'ки?
  - Проблема с сортировкой массива
  - коллизии md5
  - Странный глюк функции date
  - Скроллинг в iframe


Главная
Новости
Статьи
Шпаргалки
Файлы
О проекте
Форум
Футболки


FREEhost.com.ua - купил хостинг 10 у.е. на Begun в подарок.

iName.com.ua - регистрация доменных имен и хороший хостинг.

Библиотека программиста - нужный вам исходник или документация по необходимому для вас языку программирования.

Designclub - Клуб дизайнеров Украины.

Регистрация доменов
Хостинг

 HowtoForge.ORG.UA - Это первый Украинский ресурс развития open source программного обеспечения


Путь: Статьи > Новичкам

Новичкам

Автор: - BigDaddy
Дата публикации - 21.5.2005
Просмотров: - 3160

Загальна інфа про сесії


[p]Сесії в РНР.[/p]
[quote]При створенні веб проектів, які складаються більше, ніж з одного скрипта, часто виникає потреба передавати значення змінних між скриптами. Звичайно, це можна робити через кукі або вставляючи приховані поля в хтмл формах. Проте коли змінна є хоча б двовимірним масивом, або об"єм даних, що необхідно передати є значним, згадані способи не є дуже підходящими. Можна створювати тимчасові файли, але тоді потрібно вирішувати проблему ідентифікації для одночасного доступу кількох користувачів до ресурсу. <br>
Більшість згаданих проблем в РНР, починаючи з версії 4.0, вирішуються за допомогою сесій.[/quote]
[p]Зміст[/p]
1.Як працюють сесії?

2. Конкретно, чим корисні сесії?

3. Як запустити сесії в роботу?

4. Як же передати змінні через сесію? Як записати і де їх потім шукати?

5. Ну а хоч якийсь приклад використання сесій, щоб побачити як же воно працює разом?

6. Де і як зберігаються дані з сесії?

7. Яка тривалість життя сесії?

8. Наскільки є безпечним (захищеним) використання сесій?

9. Можливі проблеми з кешуванням сторінок які використовують сесії.

10. Переклад опису функцій для роботи з сесіями


[p]Як працюють сесії (в першому наближенні)?[/p]
Основу сесій складає механізм ідентифікації користувача та механізм збереження оточення.
При першому старті сеансу сесії генерується унікальний ідентифікатор - SID. Далі, в залежності від настройок РНР, цей ідентифікатор зберігається в користувача на комп"ютері через кукі, або автоматично додається до усіх відносних лінків якщо при компіляції --enable-trans-sid було виставлено on. Якщо при компіляції опція --enable- trans-sid off, то програмісту необхідо забезпечити передачу SID:
[code]<A HREF="nextpage.php<?php echo SID?>">click here</A>[/code]
Одночасно, в директорії, заданій в php.ini змінною session.save_path або командою session_save_path(), створюється файл з назвою SID. При повторному звернені користувача до ресурсу, якщо в кукі або в УРЛ РНР знайде ідентифікатор, який співпаде з ім"ям тимчасового файла, РНР автоматично завантажить з цього файлу всі змінні та їх значення. Цей спрощений опис механізму роботи сесій повинен дати уявлення про можливі способи їх використання.


[p]Конкретно, чим корисні сесії?[/p]
З точки зору програмування сесії дають програмісту можливість робити змінні супер глобальними, доступними для читання/зміни в будь-якому місці сайту, з будь-якого скрипта. При цьому, ця супер глобальність ні в якій мірі не зменшує безпечність та стійкість сайту до хакерських атак.


[p]Як запустити сесії в роботу?[/p]
Існує кілька способів (прийомів) роботи з сесіями. Послідовність дій приблизно наступна: потрібно стартувати сеанс роботи з сесією, об"явити змінну як сесійну і далі працювати з нею, як зі звичайною змінною, викликаючи в будь-якому скрипті.
[nb]При використанні сесій, що базуються на кукі стартувати
сесії потрібно до того, як відбувся будь-який вивід в браузер.
Очевидно, що стартувати сеанс сесії потрібно до першого звертання до сесійних
змінних. Спростити собі життя можна, виставивши session.auto_start 1 в php.ini[/nb]
Ініціалізують сеанс сесії функцією session_start().


[p]Як же передати змінні через сесію? Як записати і де їх потім шукати?[/p]
Все залежить від установки опції register_globals. Якщо ця опція виставлена в on, змінні через функцію session_register(variable) реєструються як суперглобальні. Тобто, змінна $variable буде доступною з будь-якого скрипта сайту для читання/змін. Приклад:
[code]<?php
//Увага! Цей приклад буде працювати ТІЛЬКИ якщо register_globals on!!!
//Стартуємо сеанс сесії
session_start();

//Перевіряємо, чи змінна $count була зареєстрованою через дану сесію
if (!session_is_registered('count')) {

// Якщо ні, то реєструємо і обнуляємо
session_register("count");
$count = 0;
}
else {
// Якщо змінна зареєстрована, модифікуємо її
$count++;
}
?>[/code]
Якщо session_start() не було викликано перед session_register(), остання функція викличе session_start() автоматично.


Доступ до змінних сесії можливий, також, через асоціативні масиви $HTTP_SESSION_VARS і $_SESSION. Робота через асоціативні масиви дозволяє працювати зі змінними сесії якщо register_globals виставлено значення off. При цьому, відпадає потреба у функціях типу session_register(), session_is_registered(), session_unregister(). Зі змінними сесії працювати потрібно як з елементами звичайного асоціативного масиву, наприклад, так:
[code]<?php
session_start();
if (!isset($HTTP_SESSION_VARS['count'])) {
$HTTP_SESSION_VARS['count'] = 0;
}
else {
$HTTP_SESSION_VARS['count']++;
}
?>
[/code]...або так:
[code]<?php
session_start();
if (!isset($_SESSION['count'])) {
$_SESSION['count'] = 0;
}
else {<br>
$_SESSION['count']++;
}
?>
[/code]
Від себе можу додати, що найзручніше використовувати масив $_SESSION - цей масив є глобальним. Щоб
працювати з $HTTP_SESSION_VARS всередині функцій необхідно "глобалізувати" його поставивши global модифікатор попереду:
[code]<?php global $HTTP_SESSION_VARS; ?>[/code]

[p]Ну а хоч якийсь приклад використання сесій, щоб побачити як же воно працює разом?[/p]
Розглянемо систему авторизації, коли в залежності від прав користувача йому дається доступ до певних ресурсів. В цьому випадку на головній сторінці ставиться приблизно наступний код:
[code]<?php
//Стартуємо сеанс сесії
session_start();

if(!isset($_SESSION['auth'])){
//Якщо користувач не залогований - виводимо форму логін/пароль
echo<<<EOF
<FORM METHOD=POST ACTION="login.php">
login: <INPUT TYPE=text NAME=login><BR>
password: <INPUT TYPE=password name=pass><BR>
<INPUT TYPE="submit">
</FORM>
EOF;
}
else include("main_data.php");
?>[/code]
Файл login.php містить приблизно наступний код:
[code]<?php
//Стартуємо сеанс сесії
session_start();

//Перевіряємо, що там прийшло з методом POST
if($_POST['login']==$login && $_POST['pass']==$pass){

// Якщо все ОК, встановлюємо $auth в 1
$_SESSION['auth'] = 1;

//Кидаємо користувача на відповідну сторінку, передавши ідентифікатор сесії
header("Location: url=http://yoursite.com/index.php?".SID]http://yoursite.com/index.php?".SID/url]);
else die("Login and/or password are incorrect");
?>
[/code]
Далі на будь-якій сторінці сайту вставляємо код:
[code]<?php
//Стартуємо сеанс сесії
session_start();

//Перевіряємо, чи сесійна змінна $auth є визначеною і чи не є вона порожньою
if($_SESSION['auth']) {
include("main_data.php");
.... видаємо все, що положено авторизованому користувачу
}
else {
include("default.php");
...... видаємо якусь лабуду по замовчуванню - користувач не авторизований
}
?>[/code][nb]В наведеному прикладі SID передається явно в УРЛ. Грамотно складений скрипт повинен передбачати перевірку способу передачі SID - щоб у випадку, коли кукі включені, не засмічувати УРЛ.
Якщо дозволено дозволено передачу ідентифікатора сесії через кукі, SID можна прибрати з рядка з header:
header("Location: url=http://yoursite.com/index.php"]http://yoursite.com/index.php"/url]);[/nb]
[p]Де і як зберігаються дані з сесії[/p]
Дані сесії по змовчуванню (session.save_handler=files у php.ini ви не міняли)зберігаються у файлах з наступним ім'ям:

sess_32-значний_ідентифікатор

Ці файли розміщені у папці

session.save_path=\var\lib\php\sessiondata (настройка у php.ini)

Всі змінні незалежно від їх типу (цілі, стрічки, масиви, числа з плаваючою комою) зберігаються у текстовому
файлі у вигляді стрічок. Це забезпечується процесом, який називається серіалізацією (Функція serialize(), якщо ви не міняли
параметр session.serialize_handler=php у php.ini). Зворотній процес десеріалізації здійснюється функцією unserialize().
Все це проходить без Вашого втручання і тому можете не хвилюватися як PHP зберігає дані.

Ось приклад як PHP зберігає змінні:
[code]gettext_php_loaded|b:1;gettext_php_translateStrings|a:0:{};
gettext_php_short_circuit|b:0;base_uri|s:1:"/";onetimepad|s:0:"";[/code]
Ви можете написати свої фунцкії для зберігання сесій, наприклад у базі даних, хоча у більшості випадків це не має у собі здорового глузду.
Для цього необхідно в кожній сторінці вказати директиву
[code]<?php session_set_save_handler ("open", "close", "read", "write", "destroy", "gc");?>[/code]
і написати всі функції для відкривання, закривання, зчитування, знищення і очистки сесії. (Назви функцій - довільні)
[p]Яка тривалість життя сесії[/p]
Доки користувач (броузер) в змозі передавати ідентифікатор PHP буде пам'ятати його дані.

session.gc_maxlifetime=1440 параметр у php.ini вказує скільки часу PHP буде зберігати
ці файли від часу останнього звернення. Тобто якщо на протязі цих 24 хвилин (по змовчуванню) від користувача не
буде отримано жодного запиту, сесія (її файл) знищиться.

Використання механізму сесій через cookie додатково змушує задуматись над їхнім часом життя.
Параметр session.cookie_lifetime вказує скільки броузер буде зберігати куку з ідентифікатором користувача.
По змовчуванню вона виставлена в 0, тобто діє до моменту закривання вікна броузера.
[nb]Вікна, відкриті з інших вікон (через target=_blank, javascript, Файл->Создать->Окно) мають спільні куки. Новий же запуск броузера обнуляє всі сесійні куки, незалежно від того чи відкриті ще попередні вікна[/nb]
Якщо виставити цей параметр в секундах (наприклад 86400) дасть змогу зайти користувачу на сторінку на протязі доби без втрати ідентифікатора.
[p]Наскільки є безпечним (захищеним) використання сесій[/p]
Тут є два важливих аспекти:

1. Безпечніть даних у сесії

2. Безпечність передачі ідентифікатора.

Зберігання даних у файлах з відповідною файловою системою, яка підтримує права доступу до файлів (Unix, WinNT) практично
гарантує Вам надійне зберігання даних у сесії. Доступ для файла повинен бути виключно для його власника (користувач від імені якого
запускаються скрипти: rw-----).
Найбільшим недоліком сесій є можливість перехоплення ідентифікатора, що дає змогу відкривати сторінки від чужого імені.

Які ж є способи "Кул хацкеру" отримати ідентифікатор сесії.

1. Прочитати вмсіт папки де зберігаються дані сесії, оскільки ім'я файла містить повний ідентифікатор.
[nb]Щоб уникнути цього, обов'язково перевірте щоб на папку, де зберігаються сесії (session.save_path= у php.ini) були виставлені права: rwx------. І ні в якому разі не допускайте встановлення цього шляху у папку <b>/tmp</b>[/nb]
2. Побачити ідентифікатор сесії, якщо він передається через URL на екрані користувача, у його кеші або у кеші проксі-сервера

3. Кешуючий сервер підсуне хакеру сторінку іншого клієнта, де вказаний SID.

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

Значно утруднити задачу хакера можна зберіганням IP (та X-FORWARDED) з яких сесія стартувала і на кожній сторінці перевіряти поточний IP з початковим. В разі зміни IP робити session_destroy().
[nb]Метод на працює якщо жертва і хакер сидять за двома проксі серверами[/nb]
Перевіряти ще й MAC адресу не має сенсу, з трьох причин:

1. Не зможуть працювати клієнти, що не використовують мережеві плати (dial-up)

2. MAC адресу під Unix можна взнати з ARP-таблиці, а вона оновлюється лише після пінгування адреси. Пінгування та визначеня MAC на кожній сторінці суттєво сповільнить роботу скрипта

3. Якщо хакер зумів підмінити IP, то змінити MAC для нього не складе особливих труднощів

Встановивши параметр session.referer_check= у php.ini можна перевіряти звідки прийшов користувач. Це захистить ідентифікатор від передачі іншим користувачам, пошуковим системам, іншим сайтам.
[p]Можливі проблеми з кешуванням сторінок які використовують сесії.[/p]
На сторінках де використовуються сесії (є session_start()) або на всіх сторінках, якщо
session.auto_start=1 крім інших заголовків, PHP посилає заголовки "Expire". По змовчуванню цей параметр стоїть "nocache", що означає, що
файл не буде кешуватися ні броузером ні проксі серверами і при кожному звертанні до УРЛ буди посилатися запит на нову версію файла.

Що ж тут поганого, спитаєте Ви?

Якщо користувач використовує виключно навігацію по лінках, то нічого. Але якщо використовуються кнопка "Назад", або її
javascript аналог history.back(); то можливі серйозні проблеми. Наведу три приклади:


  1. Користувач заповнює велику (або й не дуже) форму і передає її на обробку. Після аналізу сервер посилає повідомлення, що не всі поля заповнені так як потрібно і пропонує повернутись до форми через history.back().
    Але файла з формою уже ніде немає і при натисканні кнопки "Назад" користувач побачить пусту форму і, згадавши вас незлим тихим словом, почне її знову заповнювати.
  2. Скрипт виконав певні дії у базі даних (INSERT, UPDATE, DELETE) і видав повідомлення, що дані успішно/неуспішно змінено. Користувач пішов далі, але раптом схотів вернутися назад через ненависну кнопку "Назад". Скрипт знову виконався і знову видалив/вставив/обновив якісь дані. Віват! Базу запорото, незлі тихі слова летять у ваш город.
  3. Скрипт зробив певний аналіз і видав користувачу здоровенний звіт. Робота тривала 20 секунд і через погані канали (а вони завжди погані) користувач чекав цю сторінку 5 хвилин. Він помандрував далі, але тут захотів ще раз перечитати все, натиснув ненависну кнопку "Назад" Віват! Знову п'ять хвилин незлих тихих слів.

Якщо другу проблему можна вирішити за допомогою правильної архітектури, наприклад, всі файли які здійснюють операції над базою не повинні видавати ЖОДНОГО результату в разі успішних змін, а перенаправляти на інші сторінки через header('Location: path');, то від прослуховування великого кобзаря у 1 та 3 випадках вам не вберегтися.

Функція session_cache_limiter(); дозволяє змінити параметри кешування. Вона діє лише в межах однієї сторінки.

Можливі значення:[code]<?php
session_cache_limiter('nocache');
session_cache_limiter('private');
session_cache_limiter('public');
session_cache_limiter('private_no_expire'); // версії вище PHP4.2.0dev
?>[/code]
private директиву краще не викоритовувати через можливий конфуз з броузерами, виробники яких не дуже там звертають увагу на всякі RFC

'public' директива дозволить броузеру кешувати сторінку, але, о горе, вона не просто дозволить кешувати, а змусить це робити. І ніякий "refresh" не дасть вам побачити нову сторінку для УРЛ який вже раніше переглядався.
І так до тих пір, поки не вийде строк, вказаний у session.cache_expire=180 (3 години) у php.ini

Виходи два:

  1. До УРЛ доодавати якийсь випадковий параметр, наприклад mktime()
  2. Послати "лівий" заголовок, наприклад

[code]<?php
session_cache_limiter('Щоб_ти_вдавився');
?>[/code]
Броузер розгубиться і буде як кешувати, так і оновлювати свій кеш.
[p]Ну і наостанок, переклад опису функцій роботи з сесією.[/p]


session_start(void)


Створює нову або відновлює стару сесію базуючись на ідентиікаторі сесії переданого
через GET або через кукі. Функція завжди повертає TRUE. Якщо використовуються
передача ідентифікатора сесії через кукі, функцію session_start() необхідно
викликати до того, як відбудеться будь-який вивід в браузер.


При використанні іменованих сесій перед session_start() необхідно викликати session_name()


session_start() реєструє свій внутрішній хендлер виводу для модифікації УРЛ якщо РНР скомпільовано з опцією --enable-trans-sid. Тому, якщо використовується інший хендлер, як, наприклад, ob_gzhandler() слід враховувати послідовність хендлерів для отримання вірного результату.


session_destroy()


Знищує усі дані поточної сесії, при цьому самі змінні сесії зберігаються.


string session_name([string name])


Повертає/виставляє ім"я поточної сесії. Якщо ім"я name вказано - ім"я поточної сесії
змінюється. При використанні іменованих сесій перед session_start() необхідно викликати
session_name()


string session_save_path([string path])


Повертає/встановлює шлях для збереження файлів сесії


session_id([string id])


Повертає/встановлює ідентифікатор сесії. Замість цієї функції можна користуватися змінною SID.


session_register(mixed name[, mixed name2...])


Реєструє змінну (змінні) name, name2.... як глобальні змінні для поточної сесії. Якщо сеанс сесії не був ініційований session_start, його буде автоматично стартовано.
[nb]
Таким чином змінна реєструється як глобальна, з усіма наслідками. Тобто, якщо звернення до цієї змінної або реєстрація буде відбуватися в тілі функції, то необхідно забезпечити роботу власне з тією змінною, що потрібно, використавши global модифікатор.
[/nb]
Якщо використовуються відповідні асоціативні масиви ($_HTTP_SESSION_VARS, $_SESSION), то функції session_register, session_is_registered, session_unregister не використовуються.
[code]
session_register("my_var");
$my_var = "Global one, registered";

$HTTP_SESSION_VARS['my_var'] = "Don\'t need to register variable";
$_SESSION['my_var'] = "No need to register variable too";
[/code]
[nb]
Увага! Функція session_register() не присвоює якихісь значень змінній, вона просто міняє її статус.
[/nb]
session_unregister(string name)


Відміняє глобальність змінної та викидає її з сесії. Не знищує значення змінної - використовуйте unset();


session_unset()


Знищує значення усіх змінних, зареєстрованих в сесії. Змінні залишаються зареєстрованими. Для асоціативних масивів $HTTP_SESSION_VARS та $_SESSION слід використовувати unset($HTTP_SESSION_VAR['name'] або $_SESSION = array();


session_is_registered(string name)


Повертає TRUE, якщо змінна $name є зареєстрованою в даній сесії. Для асоціативних масивів $HTTP_SESSION_VARS та $_SESSION слід використовувати isset($HTTP_SESSION_VAR['name']).


array session_get_cookie_params ( void)


Повертає масив з параметрами сесійних кукі.


"lifetime" - Час життя кукі.

"path" - Шлях, де зберігається сесійна інформація

"domain" - Домен кукі.

"secure" - Кукі мають посилатися лише через безпечне з"єднання (secure connection)


void session_set_cookie_params ( int lifetime [, string path [, string domain]])


Встановлює відповідні параметри сесійних кукі (для поточної сесії). Зміни є чинними лише протягом виконання скрипта


void session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc)





Обсудить в ФОРУМе - комментариев ()


Путь: Статьи > Новичкам

Если вы заметили орфографическую, стилистическую или другую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Контакты Design by webFaction Ukrainian PHP Group 2004-2005