Доброго дня.
В даній статті ми розглянемо сесії PHP, механізм через який відбувається збереження даних сесії, і використання даного механізму у мові С++.
Розглянемо наступний PHP-код:
<?php
// page1.php
session_start() ;
echo '<meta charset="UTF-8">' ;
echo '<h1>Вітаю на сторінці сесій</h1>' ;
echo '<h2>Шлях для збереження даних сесій: '.session_save_path().'</h2>' ;
$ustr = $_SESSION ['MySiteUserName'] ;
if (strlen($ustr)==0)
{
echo 'Користувача поточної сесії не встановлено, встановлюю.' ;
$_SESSION ['MySiteUserName'] = 'UserName1' ;
$_SESSION ['cookie1'] = 'MyCookieValue1' ;
$_SESSION ['cookie2'] = 12345 ;
}
else
{
echo 'Користувач поточної сесії: ' . $ustr ;
}
?>
На самому початку скрипта використовується функція session_start(), яка ініціалізовує підсистему сесій PHP. Тобто вона перевіряє, чи не встановлена для поточного користувача сесія через файли куки або дані HTTP-запиту, і якщо так — визначає встановлені змінні для даної сесії за її ідентифікатором. На комп'ютер користувача передається тільки ID сесії, на подобі значення “aqm0g0gfpoao0ro4icvh4k2360”.
Далі відбувається вивід деякої інформації: HTML-теґ meta, який забезпечує нормальне відображення українських символів, привітання сторінки і інформація про директорію, у якій зберігаються файли усіх PHP-сесій.
Після виводу інформації, ми визначаємо значення змінної сесії “MySiteUserName”, будемо вважати, що у ній мітиться ім'я облікового запису користувача. Усі інші мета-змінні PHP-сесії, які попередньо були встановлені скриптами, можна так само отримати з змінної-масиву _SESSION, вказуючи в якості індексу назву необхідної мета-змінної. Для простоти, відкинутий механізм авторизації користувача. Якщо дана змінна пуста (її довжина рівна 0), встановлюємо необхідні значення мета-змінних поточної сесії — саму змінну в якій міститься тестове ім'я користувача і деякі дані (змінні cookie1 i cookie2). Якщо ж значення змінної сесії MySiteUserName не пусте, виводимо її на екран.
Після виконання даного скрипта на Веб-сервері можна отримати наступний результат:
Після обновлення сторінки, ми побачимо, що у нас з'явилось ім'я користувача (спрацювала підсистема PHP-сесій):
Механізм створення сесій
Сесії створюються за допомогою даних куки (Cookie), які встановлюються за допомогою HTTP-заголовка Set-Cookie (про методи POST і GET ми говорити в даному разі не будемо). Після встановлення даних куки, вони передаються між сервером і клієнтом в двосторонньому напрямку. Так сайт визначає що ви це ви, перечитуючи значення іншого HTTP-заголовку — Cookie. Даний HTTP-заголовок містить усі попередньо встановлені сервером дані.
В нашому випадку, підсистема сесій PHP встановлює тільки одну куки-змінну - PHPSESSID, яка передається від серверу до клієнта (де зберігається, найчастіше, у браузері) і від клієнта до сервера (де серверна програма на подобі Apache або Nginx зчитує її і встановлює у мета змінну HTTP_COOKIE, детально про усі мета-змінні і ви можете прочитати у статтях “Короткий опис CGI” і “CGI-програми на С++”). Усі інші дані мета-змінних сесії, зберігаються на сервері. У моєму випадку, усі дані зберігаються у каталозі “/var/lib/php5”, а дані окремих сесій зберігаються у файлі, який у своїй назві містить ідентифікатор сесії:
За допомогою даних файлів (у нашому випадку це “sess_aqm0g0gfpoao0ro4icvh4k2360”), PHP кожного разу відновлює дані сесії, коли користувач з відповідною куки-змінною, встановленою у заголовках HTTP-запиту, підключається до сервера, щоб отримати документ за певною адресою.
Встановлюємо куки за допомогою С++
Даний механізм сесії, звичайно, можна реалізувати у C/C++. Тим більше, що сам PHP реалізований на мові програмування С. Але в загальному, написати серверну програму, яка видає документи і створює сесії можна на любій мові, яка підтримує вивід тексту і даних у стандартний потік виводу, будь це С++, Python, Perl, Java чи хоч Асемблер.
Але як це зробити? Як встановити змінні куки на клієнті користувача?
Виконати дану операцію дуже просто: необхідно перед виводом заголовку типу контенту (“Content-type”) і усіх даних вивести у стандартний потік виводу заголовок “Set-Cookie:”, після якого повинні розміщуватись усі необхідні дані куки, які ви бажаєте встановити на клієнті.
В якості каркасу програми, візьмемо C++ CGI-програму з статті “CGI-програми на С++”. Там також розміщені інструкції, як налаштувати системe для запуску CGI-програм на сервері. Також зробимо модифікацію: перед усіма даними HTML-документу і заголовком “Content-Type”, виведемо додатковий HTTP-заголовок для встановлення куки-змінних:
#include <iostream>
using namespace std;
int main (int argc, char** argv)
{
// Встановлюємо куки-змінні поточного клієнта серверу
cout << "Set-Cookie: MyCPPCookie=this_is_from_kytok_org_ua\n" ;
cout << "Set-Cookie: data=12345\n" ;
// Даний HTTP-заголовок вказує, що усі наступні
// дані це HTML-код
cout << "Content-Type: text/html; charset=UTF-8\n\n" ;
// HTML-документ
//cout << "<meta charset=\"UTF-8\">" ;
cout << "<h1>Привіт, Світ! Це С++ програма, яка встановлює куки.</h1>" ;
return 0;
}
Після компіляції даного коду, встановлення у виділену директорію на сервері, можна отримати наступний результат:
Як бачимо, клієнт (в даному випадку браузер Firefox) містить куки в якості мета-змінних "MyCPPCookie" і "data", які ми попередньо встановили. Серверній C++ програмі потрібно прочитати мета змінну HTTP_COOKIE, для вияснення поточних змінних куки, щоб взнати, наприклад, авторизацію користувача, або інші необхідні параметри.
Ми також можемо імітувати поведінку підсистеми PHP-сесій, надсилаючи клієнту куки-змінну PHPSESSID з значенням унікального ідентифікатора сесії розміром у 27 символів, який потрібно попередньо згенерувати.
В даному випадку можна отримати виграш у швидкодії, використовуючи базу даних, для визначення усіх параметрів поточної сесії. Оскільки база даних (на подобі MySQL або PostgreSQL) набагато швидша ніж звичайні файли і дані у ній можна розбити по стовпцям, що не потребуватиме їхній парсинг (файл даних PHP-сесії, як показано вище, містить дані про кожну змінну - її ім'я, тип і значення). З іншої сторони, ви також можете не використовувати змінну _SESSION для збереження даних сесії (які потім відображаються у спеціальному файлі, як показано вище), а отримувати ідентифікатор PHP-сесії, і використовувати його для відновлення значень сесії з бази даних.
На жаль, при всій перевазі С++ у швидкодії перед PHP, нам необхідно самостійно реалізувати практичну усю підсистему сесій, подібну до підсистеми PHP. Тобто, необхідно реалізувати усі методи встановлення необхідних змінних Cookie з відповідними значеннями; методи зчитування значень заголовків HTTP-запиту у вигляді мета-змінної HTTP_COOKIE (і усіх інших); відновлення даних сесії з бази даних або файлу; їхнє збереження у спеціальному глобальному об'єкті. З даної точки зору PHP вирішує одну з поставлених їй задач — зменшення строків створення програми.