Sesje
HTTP jest protokołem bezstanowym, ale prawie każda aplikacja musi przechowywać stan między żądaniami, takimi jak zawartość koszyka na zakupy. Po to właśnie jest sesja. Zobaczmy,
- jak korzystać z sesji
- jak uniknąć konfliktów nazw
- jak ustawić wygaśnięcie
W przypadku korzystania z sesji, każdy użytkownik otrzymuje unikalny identyfikator zwany identyfikatorem sesji, który jest przekazywany w pliku cookie. Służy to jako klucz do danych sesji. W przeciwieństwie do plików cookie, które są przechowywane po stronie przeglądarki, dane sesyjne są przechowywane po stronie serwera.
Sesję ustawiamy w konfiguracji, szczególnie ważny jest wybór czasu wygaśnięcia.
Zarządzanie sesją jest obsługiwane przez obiekt Nette\Http\Session, do którego uzyskujesz dostęp poprzez
przekazanie go za pomocą zastrzyku zależności. W presenterech
wystarczy zadzwonić na $session = $this->getSession()
.
Rozpoczęcie sesji
Domyślnie Nette rozpoczyna sesję automatycznie w momencie, gdy zaczniemy z niej czytać lub zapisywać do niej dane. Aby
ręcznie rozpocząć sesję, użyj $session->start()
.
PHP wysyła nagłówki HTTP wpływające na buforowanie, gdy sesja jest uruchamiana, zobacz session_cache_limiter, i ewentualnie plik cookie z identyfikatorem sesji. Dlatego zawsze musisz rozpocząć sesję przed wysłaniem jakiegokolwiek wyjścia do przeglądarki, w przeciwnym razie zostanie rzucony wyjątek. Więc jeśli wiesz, że sesja będzie używana podczas renderowania strony, uruchom ją ręcznie wcześniej, być może w prezenterze.
W trybie deweloperskim Tracy uruchamia sesję, ponieważ używa jej do wyświetlania pasków przekierowań i żądań AJAX w pasku Tracy.
Sekcja
W czystym PHP, magazyn danych sesji jest zaimplementowany jako tablica dostępna poprzez zmienną globalną
$_SESSION
. Problem polega na tym, że aplikacje zwykle składają się z wielu niezależnych części, a jeśli
wszystkie z nich mają tylko jedno dostępne pole, prędzej czy później nazwy będą kolidować.
Nette Framework rozwiązuje ten problem dzieląc całą przestrzeń na sekcje ( Nette\Http\SessionSection obiekty ). Każda jednostka korzysta wtedy z własnej sekcji o unikalnej nazwie i nie może już dojść do żadnych kolizji.
Odcinek jest pozyskiwany z sesji:
$section = $session->getSection('unikatni nazev');
W prezenterze wystarczy użyć getSession()
z parametrem:
// $this jest prezenterem
$section = $this->getSession('unikatni nazev');
Aby sprawdzić istnienie odcinka, należy użyć metody $session->hasSection('unikatni nazev')
.
Sama sekcja jest następnie bardzo łatwa do pracy z wykorzystaniem metod set()
, get()
i
remove()
:
// pisanie zmiennych
$section->set('userName', 'franta');
// odczytuje zmienną, zwraca null jeśli nie istnieje
echo $section->get('userName');
// anulowanie zmiennej
$section->remove('userName');
Możesz użyć pętli foreach
, aby uzyskać wszystkie zmienne z sekcji:
foreach ($section as $key => $val) {
echo "$key = $val";
}
Ustawienia wygaśnięcia
Możliwe jest ustawienie wygasania dla poszczególnych sekcji lub nawet poszczególnych zmiennych. W ten sposób możemy pozwolić, aby login użytkownika wygasł za 20 minut, ale nadal pamiętał zawartość koszyka.
// sekcja wygasa po 20 minutach
$section->setExpiration('20 minutes');
Trzeci parametr metody set()
służy do ustawienia wygasania poszczególnych zmiennych:
// zmienna 'flash' wygasa po 30 sekundach
$section->set('flash', $message, '30 sekund');
Pamiętaj, że czas wygaśnięcia całej sesji (patrz konfiguracja sesji) musi być równy lub wyższy niż czas wygaśnięcia ustawiony dla poszczególnych sekcji lub zmiennych.
Anulowanie wcześniej ustawionego wygaśnięcia uzyskuje się za pomocą metody removeExpiration()
Metoda
remove()
zapewnia natychmiastowe anulowanie całego odcinka.
Zdarzenia $onStart, $onBeforeWrite
Obiekt Nette\Http\Session
posiada zdarzenia
$onStart
i $onBeforeWrite
, więc można dodać wywołania zwrotne, które odpalają się po rozpoczęciu
sesji lub przed jej zapisaniem na dysk, a następnie zakończeniem.
$session->onBeforeWrite[] = function () {
// zapiszemy dane do sesji
$this->section->set('basket', $this->basket);
};
Zarządzanie sesją
Przegląd metod klasy Nette\Http\Session
służących do zarządzania sesjami:
start(): void
Otworzy on sesję.
isStarted(): bool
Czy sesja została rozpoczęta?
close(): void
Kończy sesję. Sesja jest automatycznie kończona po zakończeniu działania skryptu.
destroy(): void
Kończy i usuwa sesję.
exists(): bool
Czy żądanie HTTP zawiera plik cookie z identyfikatorem sesji?
regenerateId(): void
Generuje nowy losowy identyfikator sesji. Dane są zachowane.
getId(): string
Zwraca identyfikator sesji.
Konfiguracja
Sesja jest ustawiona w konfiguracji. Jeśli piszesz aplikację, która nie korzysta z kontenera DI, do jej konfiguracji służą następujące metody. Muszą one zostać wywołane przed rozpoczęciem sesji.
setName(string $name): static
Ustawia nazwę pliku cookie, w którym przekazywany jest identyfikator sesji. Domyślna nazwa to PHPSESSID
. Jest
to przydatne, jeśli w ramach tej samej witryny uruchamiasz kilka różnych aplikacji.
getName(): string
Zwraca nazwę pliku cookie, w którym przekazywany jest identyfikator sesji.
setOptions(array $options): static
Konfiguruje sesję. Można ustawić wszystkie dyrektywy
sesji PHP (w formacie camelCase, np. zamiast session.save_path
wpisz savePath
), a także readAndClose.
setExpiration(?string $time): static
Ustawia okres bezczynności, po którym sesja wygasa.
setCookieParameters(string $path, ?string $domain=null, ?bool $secure=null, ?string $samesite=null): static
Ustawia parametry dla pliku cookie. Można zmienić domyślne wartości parametrów w konfiguracji.
setSavePath(string $path): static
Ustawia katalog, w którym przechowywane są pliki sesji.
setHandler(\SessionHandlerInterface $handler): static
Ustaw niestandardowy handler, zobacz dokumentację PHP.
W szczególności bezpieczeństwo
Serwer zakłada, że wciąż komunikuje się z tym samym użytkownikiem, dopóki żądaniom towarzyszy ten sam identyfikator sesji. Zadaniem mechanizmów bezpieczeństwa jest zapewnienie, że tak rzeczywiście jest i że identyfikator sesji nie może zostać skradziony lub sfałszowany.
Dlatego Nette Framework odpowiednio konfiguruje dyrektywy PHP, aby przekazywały identyfikator sesji tylko w ciasteczku, czyniły go niedostępnym dla JavaScript i ignorowały wszelkie identyfikatory w URL. Ponadto w krytycznych momentach, takich jak logowanie się użytkownika, wygeneruje nowy identyfikator sesji.
Do konfiguracji PHP służy funkcja ini_set, która niestety jest wyłączona przez niektóre hosty. Jeśli tak jest również w przypadku twojego hosta, spróbuj porozmawiać z nimi, aby włączyć tę funkcję lub przynajmniej skonfigurować serwer dla ciebie.