Cookies

W terminologii komputerowej ciasteczka służą do przechowywania przez przeglądarkę małych informacji (do ok 4KB) w plikach tekstowych na twoim urządzeniu. Takie zapisane informacje mogą być przechowywane do czasu zamknięcia przeglądarki (tak zwane ciasteczka dla czas sesji), lub być zapisane na jakiś dłuższy okres (np. kilkanaście dni lub dłużej). Do takich zapisanych informacji ma dostęp zarówno przeglądarka klienta, jak i serwer. Do czego to się może przydać? Na przykład do zapamiętania zalogowanego użytkownika, zapamiętania jakiś ustawień w serwisie, do przekazywania informacji między podstronami itp.

Czasy się zmieniają, tak samo zabezpieczenia przeglądarek.
Większość skryptów z tego działu będziesz musiał odpalić z serwera lokalnego. Bezpośrednio z pulpitu nie zawsze zadziałają. U mnie na Firefoxie nie mogłem usunąć ciastek, natomiast w Chrome nie mogłem ani ich utworzyć, ani usunąć. Po przeniesieniu strony na serwer lokalny wszystko śmigało jak należy (tym bardziej na serwerze produkcyjnym) :)

Postać ciasteczka

Każde ciasteczko ma postać:


CookieNazwa=cookieWartosc; expires=datawygasniecia; domain=domenaStrony; path=sciezkaURL; secure

Pierwszą część składni ciasteczka zajmuje nazwa ciasteczka oraz jego wartość. Są to jedyne wymagane parametry ciasteczka. Jeśli przeglądarka nie znajdzie cookie o danej nazwie w aktualnej domenie/ścieżce, utworzy nowe. Jeśli ciasteczko o podanej nazwie już istnieje, jego stara wartość zostanie zastąpiona przez nową.

Parametr expires określa datę wygaśnięcia. W ciasteczku data wygaśnięcia jest przechowywana w milisekundach, ale my w celu jej ustalenia musimy ją podawać w formacie GTM. Po upływie daty wygaśnięcia ciasteczko zostaje usunięte z systemu.
Jeżeli nie podamy tego parametru, wówczas ciastko zostanie utworzone do czasu trwania sesji czyli do czasu wyłączenia przeglądarki

Gdy podasz datę wygaśnięcia ciasteczka na wcześniejszą od aktualnej - wówczas takie ciasteczko zostanie usunięte.

Parametr DOMAIN określa domenę ciasteczka. Jeżeli nie ustawisz tego parametru, wówczas przeglądarka ustawi go jako nazwę serwera skąd zostało utworzone ciasteczko. Jeżeli będziesz chciał wyświetlić wszystkie ciasteczka z dokumentu cookie wówczas zostaną ci wyświetlone tylko te ciasteczka, które mają parametr domain taki jak dokument z którego wysyłasz żądanie wyświetlenia ciasteczek. Adresy domeny możesz podawać na różne sposoby - jest tylko jedno zastrzeżenie - adres taki musi zawierać przynajmniej 2 kropki np.
.pckurier.pl
.digimer.pl
Możesz też podać cały URL (<http://taka.sobie.domena/ścieżka>).

Ostatnim parametrem ciasteczka jest parametr PATH który ustawia ścieżkę skąd zostało utworzone ciasteczko. Najlepszym rozwiązaniem jest tutaj pozostawienie domyślnej wartości czyli "/".

Parametry PATH i DOMAIN wcale nie są takie opcjonalne. Jeżeli zakładasz ciastko dla całej witryny (tak by działało także na podstronach) to wtedy będziesz musiał użyć parametru path=/
Parametru DOMAIN będziesz musiał użyć, gdy w swoim serwisie korzystasz z linków rozpoczynających się od http:// i http://www (chociaż to zależy od ustawień serwera - sprawdź w praktyce).

Kolejny parametr ciasteczka to SECURE. Jeśli pominiesz ten parametr, przeglądarka automatycznie przyjmuje, że cookie dostępne jest dla każdej domeny lub programu CGI, jeśli tylko zgadzają się odpowiednie własności. Powinno się raczej pomijać ten parametr.

Tworzymy pierwsze ciasteczko

Aby utworzyć ciasteczko korzystamy z poniższej konstrukcji:


document.cookie = nazwaCookie + "=" + wartoscCookie + "; expires=" + dataWygasniecia + "; path=/"

Możemy utworzyć funkcję służącą do tworzenia ciasteczek.
Ma ona następującą postać:


function setCookie(name, val, days) {
    if (days) {
        var data = new Date();
        data.setTime(data.getTime() + (days * 24*60*60*1000));
        var expires = "; expires="+data.toGMTString();
    } else {
        var expires = "";
    }
    document.cookie = name + "=" + val + expires + "; path=/";
}

Tworzymy nowy obiekt typu date. Nasze ciastko ma wygasnąć za kilka dni (które podaliśmy w parametrze). Pobieramy więc aktualny czas, dodajemy do niego milisekundy (przeliczamy na nie podane dni), a następnie całość zamieniamy na odpowiedni zapis za pomocą metody toGMTString(). Jeżeli parametr dni nie jest ustawiony, wówczas ciastko zostanie ustawione tylko na czas włączenia przeglądarki (expires="").

Odczyt ciasteczka

Aby odczytać dane ciasteczko, musimy skorzystać z obiektu document.cookie, który jest ciągiem znaków składającym się z par nazwa=wartość.
Pomimo, iż możemy ustawić pozostałe parametry ciasteczka, to nie możemy ich odczytać. Kolejne cookie są oddzielone od siebie znakami "; ". Zauważ, że po średniku jest spacja.

Przykładowo documen.cookie może mięć wartość:


nazwacookie1=wartosccookie1; nazwacookie2=wartosccookie2; nazwacookie3=wartosccookie3;

Aby wydzielić poszczególne cookie do zmiennej tablicowej toCookie korzystamy z funkcji split.


var cookies = document.cookie.split("; ")

Jeżeli przykładowo wydrukujemy teraz cookies[1] to wyświetli nam się 2 ciasteczko w systemie (jeżeli takowe jest) czyli np. nazwacookie2=wartoscookie2. Dla takiego ciastka ponownie skorzystamy z metody split aby wydzielić nazwę i wartość ciasteczka. I tak Split("=")[0] to nazwa ciasteczka, a Split("=")[1] to wartość ciasteczka.


console.log(toCookie[0].split("=")[0]) //nazwa pierwszego ciastka
console.log(toCookie[0].split("=")[1]) //wartość pierwszego ciastka

console.log(toCookie[0]); //wypisze nazwacookie1=wartosccookie1
console.log(toCookie[0].split("=")[0] + " => " + toCookie[0].split("=")[1]); //wypisze nazwacookie1 => wartosccookie1

Możemy oczywiście odczytywać wartości poszczególnych ciasteczek jak to jest pokazane wyżej, lepiej jednak napisać funkcję, w której będziemy pobierali ciastka za pomocą nazwy:


function showCookie(name) {
    if (document.cookie!="") { //jeżeli document.cookie w ogóle istnieje
        var cookies=document.cookie.split("; ");  //tworzymy z niego tablicę ciastek
        for (var i=0; i<cookies.length; i++) { //i robimy po niej pętlę
            var cookieName=cookies[i].split("=")[0]; //nazwa ciastka
            var cookieVal=cookies[i].split("=")[1]; //wartość ciastka
            if (cookieName===name) {
                return decodeURI(cookieVal) //jeżeli znaleźliśmy ciastko o danej nazwie, wtedy zwracamy jego wartość
            }
        }
    }
}

//czytamy ciastko
console.log(showCookie("Przedmiot"));

Usuwanie ciasteczka

Aby usunąć dane ciasteczko musimy ustawić jego parametr expires na wcześniejszy od aktualnej daty. Możemy to zrobić korzystając z poniższej funkcji służącej do usuwania ciastek.


function deleteCookie(name) {
    var data = new Date();
    data.setTime(date.getMonth()-1);

    document.cookie=name + "=; expires=" + data.toGMTString();
}

Możemy też użyć pewnej sztuczki ustawiając datę wygaśnięcia danego ciastka na najniższą komputerową możliwą datę (to właśnie od tej daty komputery liczą czas).
Jakby nie patrzeć datę więc ustawimy na wcześniejszą niż obecna :)

    
function deleteCookie(name) {
    document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}

Przykład praktyczny

Załóżmy, że chcemy odczytać od użytkownika jakieś dane - np. jego imię i nazwisko, żeby móc potem z nich korzystać na innych stronach.
Tworzymy więc odpowiedni formularz:


<form name="formularz">
    <fieldset>
        <div>
            <label for="name">Podaj imię:</label>
            <input id="name" name="name" type="text" maxlength="20" length="20" />
        </div>
        
        <div>
            <label for="surname">Podaj nazwisko:</label>
            <input id="surname" name="surname" type="text" maxlength="20" length="20" />
        </div>
        
        <div>
            <input type="button" id="zapisz" value="Zapisz" />
            <input type="button" id="pokaz" value="Pokaż" />
        </div>
    </fieldset>
</form>

Następnie tworzymy odpowiedni skrypt, który utworzy nam nasze ciasteczka (1 dla imienia i 2 dla nazwiska).
Funkcje setCookie, deleteCookie i showCookie już znamy. Pozostaje je właściwie wykorzystać. Podpinamy wiec zdarzenia click pod odpowiednie guziki i w nich albo ustawiamy, albo pobieramy odpowiednie ciastka:

    
//te funkcje już znamy
function setCookie(name, val, days) {
    if (days) {
        var data = new Date();
        data.setTime(data.getTime() + (days * 24*60*60*1000));
        var expires = "; expires="+data.toGMTString();
    } else {
        var expires = "";
    }
    document.cookie = name + "=" + val + expires + "; path=/";
}

function deleteCookie(name) {
    document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}

function showCookie(name) {
    if (document.cookie!="") {
        var cookies=document.cookie.split("; ");
        for (var i=0; i<cookies.length; i++) {
            var cookieName=cookies[i].split("=")[0];
            var cookieVal=cookies[i].split("=")[1];
            if (cookieName===name) {
                return decodeURI(cookieVal)
            }
        }
    }
}

document.addEventListener("DOMContentLoaded", function() {
    //po kliknieciu guzika [zapisz] pobieramy dane z pól formularza
    //a następnie tworzymy z nimi odpowiednie ciastka
    document.getElementById('zapisz').onclick = function(e) {
        e.preventDefault(); //nie chcemy wykonywać domyślnej akcji dla tego guzika - bo to może być np wysłanie formularza - czyli poniższy kod nigdy by się nie wywołał

        var nameVal = document.getElementById('name').value;
        var surnameVal = document.getElementById('surname').value;

        setCookie('name', nameVal);
        setCookie('surname', surnameVal);
    }

    //po kliknięciu guzika [pokaz], pokazujemy alert z ciastkami
    document.getElementById('pokaz').addEventListener('click', function(e) {
        e.preventDefault();
        alert(showCookie('name') + ' ' + showCookie('surname'))
    });
});

Zapisz ciastko, przeładuj stronę, a potem zobacz czy ustawione wcześniej ciastko zostało.

Obsługa po stronie serwera

Po stronie serwera obsługa cookies także jest prosta. W poniższym przykładzie skorzystamy z PHP, w którym dostajemy dostęp do tablicy $_COOKIES:


<?php
if (isset($_COOKIE['name']) && isset(&& $_COOKIE['name'])) {
    var_dump($_COOKIE['name']); //wypisujemy utworzone w poprzednim skrypcie ciastka
    var_dump($_COOKIE['surname']);
}
?<

Oczywiście wcześniej takie ciastka muszą być utworzone, czyli albo taki serwerowy odczyt wykonamy przy wejściu na stronę, albo zrobimy to asynchronicznie za pomocą ajaxa (ewentualnie korzystając z ajaxa w jquery).