Sesje, ciasteczka i PHPSESSID

Niespodzianka

Jakiś czas temu na forum php.pl prezentowałam jeden z tutoriali, które umieściłam na tym blogu (Jak zrobić kartkę z kalendarza…). Aby zobrazować działanie przedstawionego tam kodu dałam link do projektu, który realizuję i w którym umieściłam ten kod (Polskie Stowarzyszenie Cyklistów). Ku mojemu zdumieniu użytkownicy forum, którzy chcieli ocenić ten kod w akcji zgłosili przedziwny błąd, który powodował, że strona ładowała się prawidłowo dopiero po odświeżeniu. Pozostawiłam sobie tę sprawę do późniejszego rozwiązania.

Wczoraj postanowiłam przeprowadzić walidację wspomnianego projektu, żeby usunąć ewentualne błędy w kodzie HTML oraz CSS i kilka godzin spędziłam na szukaniu błędu, którego nie było. Walidator z uporem maniaka informował mnie, że w kodzie istnieje znacznik <input>, który wbrew standardom nie został umieszczony w elemencie blokowym, a ponadto jest domknięty co jest niezgodne z zadeklarowanym typem dokumentu (HTML 4.i Strict). Nie, bo to trochę wstyd, powiem ile czasu wpatrywałam się w szablony, zeby znaleźć ten nieszczęsny input. Ile razy upewniałam się, że na serwerze mam aktualne pliki. Walidator był nieubłagany. Nie wiem co mnie podkusiło, ale postanowiłam obejrzeć źródło strony w IE (na co dzień używam FF). No cóż, przecierałam oczy ze zdumienia, bo odkryłam, że do każdego linku i do każdego formularza w źródle dopisana jest zmienna PHPSESSID. Efekt był taki, że zamiast:

<a href="/index09.php&#63;url=o_nas">O nas</a>

W źródle było

<a href="/index09.php&#63;PHPSESSID=34569786124574575324&url=o_nas">O nas</a>

Natomiast w formularzach pojawiło się ukryte pole:

<input type="hidden" name="PHPSESSID" value="34569786124574575324">

I tak oto zostałam uświadomiona co się może dziać kiedy skrypt używa sesji a przeglądarka ma wyłączone ciasteczka.

Sesje

Działanie sesji w PHP jest bardzo proste. W momencie pierwszego trafienia na stronę interpreter tworzy specjalny, losowy oraz unikalny identyfikator , który następnie przekazywany jest pomiędzy kolejnymi żądaniami (przeładowaniami strony). Identyfikator ten pozwala odczytać odpowiedni plik z danymi sesji zapisany gdzieś na serwerze. W ten sposób robi się między innymi systemy autoryzacji zapobiegając konieczności logowania się na każdej podstronie.

Aby zainicjować sesję w PHP wystarczy na początku skryptu wywołać funkcję session_start(). Otwiera to dostęp do superglobalnej tablicy $_SESSION, w której możemy przechowywać dane przeznaczone do przesyłania między kolejnymi żądaniami.

Ciasteczka

W normalnych warunkach identyfikator sesji jest przekazywany za pomocą tworzonego automatycznie ciasteczka. W normalnych warunkach to znaczy, gdy ustawienia serwera to dopuszczają a użytkownik ma włączoną obsługę ciasteczek. Jeśłi zaś konfiguracja php jest nieco inna a na dodatek użytkownik “złośliwie” wyłączy obsługę ciasteczek stanie się właśnie dokładnie to co u mnie. Do każdego kompletu danych (przesyłanych metodami GET lub POST) zostanie dodana zmienna PHPSESSID i za jej pomocą zostanie przekazana wartość identyfikatora sesji.

Jak się pozbyć PHPSESSID

Najlepiej by było zmienić nieco zawartość pliku php.ini wybierając następującą konfigurację:

session.use_only_cookies = 1
session.use_trans_sid = 0

Niestety nie zawsze jesteśmy panami własnego losu i ni zawsze mamy dostęp do plików konfiguracyjnych. Na szczęście nawet wtedy nie stoimy na straconej pozycji. Z pomocą przychodzi nam plik .htaccess. Przy jego pomocy można “lokalnie” zmienić wartości tych opcji. Wystarczy umieścić w nim następujący zapis:

php_flag use_only_cookies On
php_flag session.use_trans_sid Off

Można sobie jednak wyobrazić sytuację, że nie możemy swobodnie edytować nawet pliku .htaccess należy sięgnąć po funkcję ini_set(), która pozwala na dynamiczne ustawienie tych opcji tylko dla konkretnej aplikacji.

ini_set('use_only_cookies','On');
ini_set('session.use_trans_sid', 'Off');

Konsekwencje

Oczywiście przyjęcie takiej konfiguracji ma swoją cenę. Pozbycie się zmiennej PHPSESSID z linków i formularzy powoduje, że osoba, która w swojej przeglądarce ma wyłączone ciasteczka w zasadzie będzie miała ograniczone możliwości jeśli chodzi o korzystanie ze stworzonej przez nas aplikacji. Przykre konsekwencje polegają na tym, że taki użytkownik będzie musiał logować się na każdej podstronie, gdyż w jego przypadku przekazywanie identyfikatora sekcji pomiędzy żądaniami nie będzie możliwe.

4 komentarze do wpisu „Sesje, ciasteczka i PHPSESSID”

  1. Artykuł typowo informujący, jak zwykle przyjemnie się czyta.
    Gdzie jednak informacje dodatkowe JAK wspomóc skrypt by problem chociaż w minimalnym stopniu zredukować? Gdy ktoś ma wyłączone ciasteczka wystarczy dodawać przez GET lub POST jakiś losowy string tylko dla tej osoby (co się powinno zapisać też w bazie razem z pełną zawartością agenta przeglądającego). Wtedy na kolejnej stronie wystarczy sprawdzić czy agent i nasz mini hash są takie samo jak poprzednio.
    To oczywiście tylko taka mała sugestia i zakrawa o pisanie własnego systemu sesji. Jednak moim zdaniem warto właśnie o jakimś innym rozwiązaniu – zastępczym – wspomnieć.

Leave a Reply

%d bloggers like this: