Przechowywanie danych w przeglądarce - cookies
Rozpoczynamy serię lekcji, w których ostatecznie zajmiemy się logowaniem użytkownika i nadawaniem mu odpowiednich uprawnień w aplikacji, ale zanim tam dojdziemy, musimy przejść przez kilka kroków. Pierwszym krokiem będzie poznanie dość starego, ale wciąż używanego mechanizmu przechowywania danych po stronie przeglądarki użytkownika.
Wideo towarzyszące
Czym są cookies i jak działają?
Cookies to krótkie informacje tekstowe, które serwer wysyła do przeglądarki, a przeglądarka następnie odsyła te informacje do serwera w kolejnych żądaniach.
Konkretnie, w odpowiedzi na żądanie HTTP serwer może umieścić w odpowiedzi nagłówek w takiej postaci:
Set-Cookie: <nazwa>=<wartosc>Czyli jeżeli, na przykład, nasza aplikacja będzie oferować różne schematy kolorystyczne, jasny i ciemny, a użytkownik wybierze przełączenie aplikacji w ciemniejszy schemat, w odpowiedzi serwer może odesłać w odpowiedzi nagłówek:
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: colorscheme=dark
[dokument html]W takim przypadku przeglądarka użytkownika wysyłając kolejne żądanie dopisze do niego dodatków nagłówek w takiej postaci:
GET /jakas/sciezka HTTP/2.0
Host: example.com
Cookie: colorscheme=darkW ten sposób nasz serwer będzie wiedział, żeby serwować użytkownikowi strony w odpowiedniej palecie kolorystycznej.
Alternatywnie moglibyśmy umieścić to ustawienie np. w linkach jako query parameter, tj. ?colorscheme=dark ale to miałoby kilka wad: po pierwsze, musielibyśmy pamiętać o dodaniu odpowiedniego stringu do wszystkich linków generowanych na stronie, a po drugie w ten sposób jeżeli nasz użytkownik wysłałby link do naszej strony do znajomego, automatycznie ustawilibyśmy dla nowo przybyłego użytkownika taki sam schemat kolorystyczny. Nie jest to poważna wada, ale pokazuje co trzeba rozważać, kiedy podejmujemy decyzję o tym, gdzie przechowywać daną informację.
Typowe zastosowania cookies
Najczęstsze zastosowania cookies to:
- Przechowywanie preferencji i wyborów użytkownika
- Identyfikacja zalogowanych użytkowników
- Analityka statystyczna i sprawdzanie zachowań użytkowników
Istnieją bardziej niszowe zastosowania cookies i może do nich jeszcze wrócimy, dziś skupimy się na pierwszym zastosowaniu. W zależności od zastosowania naszej aplikacji, możemy oferować użytkownikowi różne ustawienia. Może być to język wyświetlanej strony, waluta w której pokazujemy ceny, potencjalny kraj do wysyłki towarów albo strefa czasowa, w której przebywa nasz użytkownik i wiele, wiele innych.
Innym zastosowaniem z tej kategorii jest przechowywanie informacji np. o ostatnio przeglądanych podstronach naszej aplikacji. W przypadku aplikacji do fiszek możemy sobie wyobrazić sytuację, w której mamy w aplikacji dziesiątki kategorii, ale możemy podsunąć użytkownikowi pod nos np. 5 ostatnio przez niego odwiedzanych, ponieważ jest spore prawdopodobieństwo, że obecnie próbuje opanować jakiś konkretny materiał i może wracać do konkretnych zestawów fiszek.
W przypadku aplikacji typu sklep internetowy możemy pokazywać użytkownikowi ostatnio oglądane produkty albo inne z tej samej kategorii.
Jednym z podstawowych zastosowań analitycznych jest monitorowanie “nowych” odwiedzających, ponieważ jeżeli nasza aplikacja ustawi jakieś cookie domyślnie dla każdego odwiedzającego, to żądanie przychodzące bez takiego cookie prawdopodobnie pochodzi od nowego użytkownika. Niestety tylko prawdopodobnie, ponieważ użytkownicy mają pełną kontrolę nad cookies przechowywanymi w ich przeglądarce i mogą je bez naszej wiedzy usunąć albo użyć np. programu curl albo trybu incognito i w ten sposób zaburzyć nasze statystyki.
Jak długo żyją cookies?
Cookie ustawione przez serwer przy pomocy samego nagłówka Set-Cookie będzie przechowywane w przeglądarce do czasu zamknięcia danej zakładki lub okna. Jeżeli chcemy żeby dane w cookie przetrwały zamknięcie przeglądarki, musimy dodatkowo podać, jak długo dane pozostają ważne. Możemy to zrobić na dwa sposoby, dodając do cookie parametr Max-Age albo Expires. Używając poprzedniego przykładu, nasze cookie colorscheme mogłoby być ustawione na takie sposoby:
Set-Cookie: colorscheme=dark; Expires=Sat, 10 Jan 2026 10:11:12 GMT;
Set-Cookie: colorscheme=dark; Max-Age=2592000W pierwszym przypadku podajemy dokładną datę i godzinę wygaśnięcia danych, po których przeglądarka usunie cookie i przestanie je wysyłać do serwera. W drugim przypadku podajemy czas w milisekundach do momentu wygaśnięcia cookie. O ile druga opcja jest mniej czytelna na pierwszy rzut oka, o tyle eliminuje problem w różnicach ustawieniach dat pomiędzy serwerem i przeglądarką.
Modyfikowanie cookies
Modyfikowanie cookies odbywa się poprzez ponowne ustawienie cookie o tej samej nazwie i parametrach z uwzględnieniem nowej wartości. W ten sposób możemy też przedłużać ważność cookie, ustawiając mu tę samą wartość, ale wysyłając nową datę wygaśnięcia cookie.
Usuwanie cookies
Jeżeli nasz serwer ustawił jakieś cookie w przeglądarce użytkownika, ale chciałby je usunąć, np. w celu wylogowania użytkownika, to powinien w odpowiedzi na żądanie użytkownika wysłać nagłówek Set-Cookie z podaną wcześniej nazwą oraz parametrem Expires ustawionym w przeszłości albo parametrem Max-Age o wartości zero lub negatywnej. Nie jest to najbardziej intuicyjny interfejs, ale jeżeli koniecznie potrzebujemy usunąć jakieś konkretne cookie, to nie mamy innego wyboru.
W przyszłych lekcjach omówimy inne strategie usuwania cookies z przeglądarki ze strony serwera.
Gdzie znaleźć więcej informacji
Większość informacji i wiele więcej znajdziecie w przewodniku MDN poświęconemu cookies oraz czytając dodatkowe informacje do których ten przewodnik linkuje.
Wymagania prawne związane z cookies
Ważne Nie jestem prawnikiem. Jeżeli potrzebujesz pewnej informacji z zakresu prawnego, skonsultuj się z odpowiednim specjalistą.
To powiedziawszy, zarówno Unia Europejska jak i część Stanów Zjednoczonych Ameryki wprowadziła obwarowania prawne, które ograniczają swobodne korzystanie z cookies przez programistów tworzących aplikacje internetowe.
Podstawowe przesłanie tych dokumentów prawnych jest dość proste. Użytkownik musi:
- zostać poinformowany o tym, że nasza strona korzysta z cookies i w jakim celu,
- móc odrzucić wykorzystanie cookies, które nie są niezbędne dla działania aplikacji
Co to znaczy niezbędne dla działania aplikacji? Tu zaczynają się schody. Pewnie każdy się zgodzi, że sklep internetowy musi mieć możliwość przechowywania informacji o produktach zebranych w koszyku użytkownika w celu obsłużenia jego zakupów. Być może to samo powiemy o preferencjach językowych na stronie hotelu. Ale czy możliwość wybrania odpowiedniego do ekranu schematu kolorystycznego to nadal niezbędne do działania dane? Osobiście uważam, że tak bo jest to kwestia dostępności aplikacji dla wszystkich użytkowników, ale pewnie znajdą się głosy sprzeciwu. W każdym razie jedno pozostaje pewne: jeżeli korzystamy z cookies musimy poinformować o tym użytkownika i mieć kontrolę nad tym, na co użytkownik się zgadza, a na co nie.
Jeżeli jesteś zainteresowanx, to polecam stronę GDPR poświęconą tym wymaganiom prawnym, gdzie autorzy dość prostym językiem tłumaczą, jakie obowiązki spoczywają na autorach stron internetowych.
Przykład użycia cookies w naszej aplikacji
W repozytorium z kodem do naszych lekcji znajduje się folder dedykowany dla aktualnego materiału, a w nim kolejne podfoldery:
01_start
Jako punkt wyjścia, zawierający kod aplikacji z końca poprzedniej lekcji.
02_cookies_theme
Implementacja wyboru pomiędzy jasnym i ciemnym tematem kolorystycznym aplikacji.
W tym wypadku musiałem przerobić sporo elementów aplikacji:
- Usunąłem statyczną stronę startową obsługującą ścieżkę
/i usunąłem prefix/cardsz wszystkich handlerów związanych z fiszkami, ponieważ jest to główna funkcjonalność naszej aplikacji. - Przeredagowałem niemalże wszystkie widoki ponieważ chciałem ujednolicić elementy nawigacyjne oraz umieścić przełącznik tematu kolorystycznego w logicznym miejscu.
Najważniejsze zmiany jednak zawierają się w czterech plikach:
| |
- W liniach 3 i 15 wykorzystujemy nowy zewnętrzny moduł potrzebny nam do obsługi cookies,
cookie-parser - W linii 6 pojawia się nowy model zawierający nasz moduł z ustawieniami aplikacji
- W liniach 17-19 konfigurujemy nowy handler, który będzie nam służył do obsługi ustawień. W tym celu zgrupujemy funkcje obsługujące ustawienia w routerze frameworku express, który następnie podpinamy w linii 19 pod ścieżkę
/settings. Oznacza to że funkcjasettings.themeTogglebędzie uruchomiona do obsługi ścieżki/settings/toggle-theme - W liniach 21-26 tworzymy proste middleware które pozwoli naszym widokom na dostęp do zmiennych ustawień pod zmienną
apporaz do ścieżki obecnie obsługiwanego żądania pod zmiennąpath.
| |
- W linii drugiej ustawiamy na elemencie
htmldodatkowy parametrdata-theme, który będzie sterował doborem kolorów w szablonie CSS - W liniach 13-15 dla stron niebędących stroną główną będziemy wyświetlać link pozwalający na powrót do niej.
- W liniach 18-28 tworzymy link, który prowadzi do ścieżki
/settings/toggle-theme, który pozwoli nam przełączyć temat kolorystyczny aplikacji. Zwróć uwagę, że dodajemy tam query parameterpage, który pozwoli nam wrócić do aktualnej strony
Dodatkowa zagadka: gdyby zmienna app istniała, ale nie miała właściwości theme, jaki temat uznajemy za domyślny? Jasny czy ciemny?
| |
- W linii 7 widzimy przykład pobrania wartości cookie z żądania. Jeżeli cookie nie istnieje JS zwróci nam wartość
undefined, co musimy odpowiednio obsłużyć. - W linii 13 ustawiamy nowe cookie z odpowiednią wartością
- W linii 21 widzimy przykład często stosowanej składni do ustawienia domyślnej wartości dla zmiennej. Jeżeli wyrażenie po lewej stronie operatora
||będzie “fałszywe”, w co wlicza się między innymi wartośćundefined, zostanie użyta wartość na prawo od operatora||.
| |
W pliku CSS definiujemy kolory używane w aplikacji jako zmienne CSS. Pierwsza definicja będzie używana domyślnie. Druga, bardziej specyficzna zostanie użyta tylko wtedy, kiedy element html będzie miał atrybut data-theme ustawiony na wartość dark.
03_cookie_consent
Implementacja banneru pozwalającego użytkownikowi wyrażenie zgody na użycie wszelkich cookies bądź odrzucenie użycia nieobowiązkowych danych. Implementacja bazuje na rozwiązaniu opublikowanym na tej stronie.
Przeanalizuj samodzielnie zmiany w plikach:
models/settings.jsviews/foot.partial.ejspublic/css/style.css
04_last_viewed_feature
Dodanie do naszej aplikacji wyświetlania listy ostatnio przeglądanych kategorii fiszek z uwzględnieniem faktu, że użytkownik mógł się na tę funkcjonalność nie zgodzić.
Najważniejsze zmiany sprowadzają się do dwóch plików:
| |
- W liniach 51-61, jeżeli użytkownik wyraził zgodę, komponujemy listę identyfikatorów ostatnio odwiedzonych kategorii. Ponieważ dane pochodzące od użytkownika mogą być niewłaściwie sformatowane, musimy odpowiednio obsłużyć przypadki brzegowe. Próbujemy więc najpierw pobrać zawartość cookie, a następnie upewnić się, że ma spodziewany format listy liczb całkowitych oddzielonych przecinkami. Następnie tworzymy listę zawierającą najpierw obecnie odwiedzaną kategorię, a potem dwie kolejne, które były wcześniej na liście.
- W liniach 34-40 próbujemy wykorzystać listę stworzoną w poprzednim kroku. Znów, ponieważ dane przychodzące od użytkownika mogą być niepoprawne, staramy się odczytać listę liczb stałych oddzielonych przecinkami, a następnie pobieramy z naszego modelu podsumowania kategorii na podstawie uzyskanych id kategorii.
Wyświetlanie listy jest obsłużone w szablonie EJS warunkowo:
| |
Bezpieczeństwo cookies
Dokładniej temat bezpieczeństwa cookies i związanych z nimi zagrożeń omówimy sobie na następnej lekcji. Teraz podkreślę pierwszą zasadę związaną z cookies dla nas jako programistów aplikacji webowych: cookies są danymi przychodzącymi z zewnątrz i należy je traktować adekwatnie: jak skażone, radioaktywne odpady, póki nie zweryfikujemy, że zawierają oczekiwane przez nas informacje. Użytkownicy mają pełną kontrolę nad danymi w swojej przeglądarce i tak powinno być. Ale dla nas to oznacza, że mogą je dowolnie modyfikować, usuwać i dodawać, więc pamiętaj: cookies podlegają walidacji i weryfikacji przed użyciem jak wszystkie inne dane z zewnątrz. Dodatkowo miejmy na uwadze, że żądania do naszego serwera nie muszą pochodzić z przeglądarki, nie raz korzystaliśmy z narzędzia curl do sprawdzania naszej aplikacji i tam również użytkownik ma pełną kontrolę nad zawartością wysyłanych cookies. Musimy mieć się na baczności.
Zadanie praktyczne
Ścieżka /settings/manage-cookies obsługiwana przez funkcję manageCookies z pliku models/settings.js jest właściwie nieobsłużona. Dopisz własną obsługę tej ścieżki pozwalającą co najmniej na zmianę zgody na zastosowanie cookies przez użytkownika. W przypadku cofnięcia zgody, pamiętaj aby usunąć cookies, które nie są niezbędne dla funkcjonowania aplikacji.