Soubory cookie, document.cookie

Cookies jsou malé řetězce dat, které se ukládají přímo v prohlížeči. Jsou součástí protokolu HTTP, definovaného specifikací RFC 6265.

Cookies obvykle nastavuje webový server pomocí odpovědi Set-Cookie HTTP hlavička. Poté je prohlížeč automaticky přidá do (téměř) každého požadavku do stejné domény pomocí Cookie HTTP-header.

Jedním z nejrozšířenějších případů použití je autentizace:

  1. Po přihlášení použije server Set-Cookie HTTP hlavička v odpovědi pro nastavení cookie s jedinečným „identifikátorem relace“.
  2. Když je příště požadavek odeslán do stejné domény, prohlížeč odešle soubor cookie přes síť pomocí Cookie záhlaví HTTP.
  3. Takže server ví, kdo podal požadavek.

K cookies máme také přístup z prohlížeče pomocí document.cookie vlastnost.

Na cookies a jejich možnostech je mnoho záludných věcí. V této kapitole se jim budeme podrobně věnovat.

Čtení z document.cookie

Ukládá váš prohlížeč nějaké soubory cookie z tohoto webu? Podívejme se:

// At javascript.info, we use Google Analytics for statistics,
// so there should be some cookies
alert( document.cookie ); // cookie1=value1; cookie2=value2;...

Hodnota document.cookie sestává z name=value párů, oddělených ; . Každý z nich je samostatný soubor cookie.

Abychom našli konkrétní cookie, můžeme rozdělit document.cookie podle ; a poté najděte správný název. K tomu můžeme použít regulární výraz nebo funkce pole.

Necháme to jako cvičení pro čtenáře. Na konci kapitoly také najdete pomocné funkce pro manipulaci se soubory cookie.

Zápis do document.cookie

Můžeme zapisovat do document.cookie . Ale to není vlastnost dat, je to přístupový objekt (getter/setter). Úkol k němu je zpracován speciálně.

Operace zápisu na document.cookie aktualizuje pouze soubory cookie v něm uvedené, ale netýká se jiných souborů cookie.

Toto volání například nastaví soubor cookie s názvem user a hodnotu John :

document.cookie = "user=John"; // update only cookie named 'user'
alert(document.cookie); // show all cookies

Pokud jej spustíte, pravděpodobně uvidíte více souborů cookie. Je to proto, že document.cookie= operace nepřepíše všechny soubory cookie. Nastaví pouze zmíněnou cookie user .

Technicky může mít název a hodnota libovolné znaky. Aby bylo zachováno platné formátování, měly by být escapovány pomocí vestavěného encodeURIComponent funkce:

// special characters (spaces), need encoding
let name = "my name";
let value = "John Smith"

// encodes the cookie as my%20name=John%20Smith
document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value);

alert(document.cookie); // ...; my%20name=John%20Smith
Omezení

Existuje několik omezení:

  • name=value pár za encodeURIComponent , by neměla přesáhnout 4 kB. Takže do cookie nemůžeme uložit nic velkého.
  • Celkový počet souborů cookie na doménu je omezen na přibližně 20+, přesný limit závisí na prohlížeči.

Soubory cookie mají několik možností, mnohé z nich jsou důležité a měly by být nastaveny.

Možnosti jsou uvedeny za key=value , oddělený ; , takto:

document.cookie = "user=John; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"

cesta

  • path=/mypath

Předpona cesty url musí být absolutní. Zpřístupňuje soubor cookie pro stránky pod touto cestou. Ve výchozím nastavení je to aktuální cesta.

Pokud je soubor cookie nastaven na path=/admin , je vidět na stránkách /admin a /admin/something , ale ne na /home nebo /adminpage .

Obvykle bychom měli nastavit path do kořenového adresáře:path=/ aby byl soubor cookie dostupný ze všech webových stránek.

doména

  • domain=site.com

Doména definuje, kde je soubor cookie přístupný. V praxi však existují omezení. Nemůžeme nastavit žádnou doménu.

Neexistuje žádný způsob, jak umožnit přístup k souboru cookie z jiné domény 2. úrovně, takže other.com nikdy neobdrží soubor cookie nastavený na site.com .

Jde o bezpečnostní omezení, které nám umožňuje ukládat citlivá data v souborech cookie, které by měly být dostupné pouze na jednom webu.

Ve výchozím nastavení je soubor cookie přístupný pouze v doméně, která jej nastavila.

Upozorňujeme, že ve výchozím nastavení není soubor cookie sdílen také se subdoménou, jako je forum.site.com .

// if we set a cookie at site.com website...
document.cookie = "user=John"

// ...we won't see it at forum.site.com
alert(document.cookie); // no user

…To se ale dá změnit. Pokud bychom chtěli povolit subdomény jako forum.site.com získat soubor cookie nastavený na site.com , to je možné.

Aby k tomu došlo, při nastavení souboru cookie na site.com , měli bychom explicitně nastavit domain možnost do kořenové domény:domain=site.com . Takový soubor cookie pak uvidí všechny subdomény.

Například:

// at site.com
// make the cookie accessible on any subdomain *.site.com:
document.cookie = "user=John; domain=site.com"

// later

// at forum.site.com
alert(document.cookie); // has cookie user=John

Z historických důvodů domain=.site.com (s tečkou před site.com ) funguje také stejným způsobem a umožňuje přístup k souboru cookie ze subdomén. To je stará notace a měla by být použita, pokud potřebujeme podporovat velmi staré prohlížeče.

Abych to shrnul, domain možnost umožňuje zpřístupnit soubor cookie na subdoménách.

vyprší, maximální věk

Ve výchozím nastavení, pokud cookie nemá jednu z těchto možností, zmizí po zavření prohlížeče. Takové soubory cookie se nazývají „soubory cookie relace“

Aby soubory cookie přežily zavření prohlížeče, můžeme nastavit buď expires nebo max-age možnost.

  • expires=Tue, 19 Jan 2038 03:14:07 GMT

Datum vypršení platnosti cookie určuje čas, kdy jej prohlížeč automaticky smaže.

Datum musí být přesně v tomto formátu, v časovém pásmu GMT. Můžeme použít date.toUTCString dostat to. Můžeme například nastavit, aby platnost souboru cookie vypršela za 1 den:

// +1 day from now
let date = new Date(Date.now() + 86400e3);
date = date.toUTCString();
document.cookie = "user=John; expires=" + date;

Pokud nastavíme expires k datu v minulosti se soubor cookie smaže.

  • max-age=3600

Je alternativou k expires a určuje vypršení platnosti souboru cookie v sekundách od aktuálního okamžiku.

Pokud je nastaveno na nulu nebo zápornou hodnotu, soubor cookie se odstraní:

// cookie will die in +1 hour from now
document.cookie = "user=John; max-age=3600";

// delete cookie (let it expire right now)
document.cookie = "user=John; max-age=0";

bezpečné

  • secure

Soubor cookie by měl být přenášen pouze přes HTTPS.

Ve výchozím nastavení, pokud nastavíme soubor cookie na http://site.com , pak se také objeví na https://site.com a naopak.

To znamená, že soubory cookie jsou založeny na doméně, nerozlišují mezi protokoly.

S touto možností, pokud je soubor cookie nastaven pomocí https://site.com , pak se nezobrazí, když se na stejný web přistupuje pomocí HTTP, jako http://site.com . Pokud tedy soubor cookie obsahuje citlivý obsah, který by se nikdy neměl odesílat přes nešifrovaný protokol HTTP, secure vlajka je správná věc.

// assuming we're on https:// now
// set the cookie to be secure (only accessible over HTTPS)
document.cookie = "user=John; secure";

stejný web

To je další bezpečnostní atribut samesite . Je navržen tak, aby chránil před takzvanými XSRF (cross-site request forgery) útoky.

Abychom pochopili, jak to funguje a kdy je to užitečné, podívejme se na útoky XSRF.

Útok XSRF

Představte si, že jste přihlášeni na stránce bank.com . To znamená:z tohoto webu máte ověřovací soubor cookie. Váš prohlížeč jej odešle na bank.com s každou žádostí, aby vás poznal a provedl všechny citlivé finanční operace.

Nyní při procházení webu v jiném okně omylem přejdete na jiný web evil.com . Tento web obsahuje kód JavaScript, který odesílá formulář <form action="https://bank.com/pay"> na bank.com s poli, která iniciují transakci na účet hackera.

Prohlížeč odesílá soubory cookie pokaždé, když navštívíte web bank.com , i když byl formulář odeslán z evil.com . Banka vás tedy pozná a skutečně provede platbu.

Jde o takzvaný útok „Cross-Site Request Forgery“ (ve zkratce XSRF).

Skutečné banky jsou před ním samozřejmě chráněny. Všechny formuláře generované bank.com mají speciální pole, takzvaný „ochranný token XSRF“, které zlá stránka nemůže vygenerovat ani extrahovat ze vzdálené stránky. Může tam odeslat formulář, ale nemůže získat data zpět. Web bank.com zkontroluje tento token v každé podobě, kterou obdrží.

Implementace takové ochrany však nějakou dobu trvá. Musíme zajistit, aby každý formulář měl požadované pole tokenu, a také musíme zkontrolovat všechny požadavky.

Zadejte možnost cookie samesite

Soubor cookie samesite Tato možnost poskytuje další způsob ochrany před takovými útoky, který by (teoreticky) neměl vyžadovat „ochranné tokeny xsrf“.

Má dvě možné hodnoty:

  • samesite=strict (stejné jako samesite bez hodnoty)

Soubor cookie s samesite=strict se nikdy neodešle, pokud uživatel pochází z jiné stránky.

Jinými slovy, zda uživatel následuje odkaz ze své pošty nebo odešle formulář z evil.com nebo provede jakoukoli operaci, která pochází z jiné domény, soubor cookie se neodešle.

Pokud mají ověřovací soubory cookie samesite možnost, pak nemá útok XSRF šanci na úspěch, protože odeslání z evil.com přichází bez cookies. Takže bank.com nerozpozná uživatele a nebude pokračovat v platbě.

Ochrana je poměrně spolehlivá. Pouze operace, které pocházejí z bank.com odešle samesite sušenka, např. odeslání formuláře z jiné stránky na bank.com .

I když je tu malá nepříjemnost.

Když uživatel následuje legitimní odkaz na bank.com , jako z jejich vlastních poznámek, budou překvapeni, že bank.com je nepoznává. Opravdu, samesite=strict soubory cookie se v takovém případě neodesílají.

Mohli bychom to obejít použitím dvou souborů cookie:jeden pro „obecné rozpoznání“, pouze pro účely říci:„Ahoj, Johne“, a druhý pro operace změny dat s samesite=strict . Poté se osobě přicházející mimo web zobrazí uvítací zpráva, ale aby bylo možné odeslat druhý soubor cookie, musí být platby zahájeny z webových stránek banky.

  • samesite=lax

Uvolněnější přístup, který také chrání před XSRF a nenarušuje uživatelský dojem.

Laxní režim, stejně jako strict , zakazuje prohlížeči odesílat soubory cookie při příchodu z jiných stránek, ale přidává výjimku.

A samesite=lax cookie se odešle, pokud jsou splněny obě tyto podmínky:

  1. Metoda HTTP je „bezpečná“ (např. GET, ale ne POST).

    Úplný seznam bezpečných metod HTTP je ve specifikaci RFC7231. V zásadě se jedná o metody, které by měly být použity pro čtení, ale nikoli pro zápis dat. Nesmí provádět žádné operace změny dat. Následování odkazu je vždy GET, bezpečná metoda.

  2. Operace provede navigaci na nejvyšší úrovni (změní adresu URL v adresním řádku prohlížeče).

    To je obvykle pravda, ale pokud se navigace provádí v <iframe> , pak to není na nejvyšší úrovni. Metody JavaScriptu pro síťové požadavky také neprovádějí žádnou navigaci, a proto se nehodí.

Takže, co samesite=lax je v zásadě umožnit nejběžnější operaci „přejít na URL“ mít soubory cookie. Např. otevření odkazu na webovou stránku z poznámek, které splňují tyto podmínky.

Ale cokoli složitějšího, jako je síťový požadavek z jiného webu nebo odeslání formuláře, ztratí soubory cookie.

Pokud vám to vyhovuje, přidejte samesite=lax pravděpodobně nenaruší uživatelské prostředí a nepřidá ochranu.

Celkově samesite je skvělá volba.

Má to nevýhodu:

  • samesite je ignorován (nepodporován) velmi starými prohlížeči z roku 2017 nebo tak.

Pokud se tedy budeme spoléhat pouze na samesite zajistit ochranu, pak budou staré prohlížeče zranitelné.

Ale určitě můžeme použít samesite spolu s dalšími ochrannými opatřeními, jako jsou tokeny xsrf, abychom přidali další vrstvu obrany, a pak v budoucnu, až staré prohlížeče vymřou, pravděpodobně budeme moci tokeny xsrf zahodit.

Pouze http

Tato možnost nemá nic společného s JavaScriptem, ale pro úplnost ji musíme zmínit.

Webový server používá Set-Cookie záhlaví pro nastavení cookie. Může také nastavit httpOnly možnost.

Tato možnost zakáže jakýkoli JavaScriptový přístup k souboru cookie. Takový soubor cookie nemůžeme vidět ani s ním manipulovat pomocí document.cookie .

To se používá jako preventivní opatření k ochraně před určitými útoky, když hacker vloží svůj vlastní kód JavaScript na stránku a čeká, až uživatel tuto stránku navštíví. To by vůbec nemělo být možné, hackeři by neměli mít možnost vložit svůj kód na naše stránky, ale mohou se vyskytnout chyby, které jim to umožní.

Normálně, pokud se taková věc stane a uživatel navštíví webovou stránku s hackerovým kódem JavaScript, pak se tento kód spustí a získá přístup k document.cookie s uživatelskými cookies obsahujícími autentizační informace. To je špatné.

Ale pokud je cookie httpOnly a poté document.cookie nevidí, takže je chráněný.

Příloha:Funkce souborů cookie

Zde je malá sada funkcí pro práci se soubory cookie, pohodlnější než ruční úprava document.cookie .

Na to existuje mnoho knihoven souborů cookie, takže tyto jsou pro účely ukázky. Nicméně plně funkční.

getCookie(název)

Nejkratší způsob přístupu k cookie je použití regulárního výrazu.

Funkce getCookie(name) vrátí cookie s daným name :

// returns the cookie with the given name,
// or undefined if not found
function getCookie(name) {
  let matches = document.cookie.match(new RegExp(
    "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
  ));
  return matches ? decodeURIComponent(matches[1]) : undefined;
}

Zde new RegExp je generován dynamicky, aby odpovídal ; name=<value> .

Upozorňujeme, že hodnota souboru cookie je zakódována, takže getCookie používá vestavěný decodeURIComponent funkci pro její dekódování.

setCookie(název, hodnota, možnosti)

Nastaví name souboru cookie na daný value s path=/ ve výchozím nastavení (lze upravit a přidat další výchozí hodnoty):

function setCookie(name, value, options = {}) {

  options = {
    path: '/',
    // add other defaults here if necessary
    ...options
  };

  if (options.expires instanceof Date) {
    options.expires = options.expires.toUTCString();
  }

  let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value);

  for (let optionKey in options) {
    updatedCookie += "; " + optionKey;
    let optionValue = options[optionKey];
    if (optionValue !== true) {
      updatedCookie += "=" + optionValue;
    }
  }

  document.cookie = updatedCookie;
}

// Example of use:
setCookie('user', 'John', {secure: true, 'max-age': 3600});

deleteCookie(name)

Chcete-li soubor cookie smazat, můžeme jej zavolat se záporným datem vypršení platnosti:

function deleteCookie(name) {
  setCookie(name, "", {
    'max-age': -1
  })
}
Aktualizace nebo smazání musí používat stejnou cestu a doménu

Vezměte prosím na vědomí:když aktualizujeme nebo smažeme soubor cookie, měli bychom použít přesně stejné možnosti cesty a domény, jaké jsme nastavili.

Společně:cookie.js.

Příloha:Soubory cookie třetích stran

Soubor cookie se nazývá „třetí strana“, pokud je umístěn jinou doménou, než je stránka, kterou uživatel navštěvuje.

Například:

  1. Stránka na adrese site.com načte banner z jiného webu:<img src="https://ads.com/banner.png"> .

  2. Spolu s bannerem i vzdálený server na ads.com může nastavit Set-Cookie záhlaví se souborem cookie jako id=1234 . Takový soubor cookie pochází z ads.com domény a bude viditelný pouze na ads.com :

  3. Příště až ads.com při přístupu, vzdálený server obdrží id cookie a rozpozná uživatele:

  4. Ještě důležitější je, když se uživatel přesune z site.com na jiný web other.com , který má také banner, pak ads.com získá cookie, protože patří k ads.com , čímž rozpozná návštěvníka a sleduje ho, když se pohybuje mezi weby:

Soubory cookie třetích stran se kvůli své povaze tradičně používají pro sledování a reklamní služby. Jsou vázány na původní doménu, tedy ads.com může sledovat stejného uživatele mezi různými weby, pokud k nim všichni přistupují.

Některým lidem se přirozeně nelíbí být sledováni, takže prohlížeče umožňují takové soubory cookie zakázat.

Některé moderní prohlížeče také používají speciální zásady pro takové soubory cookie:

  • Safari vůbec nepovoluje soubory cookie třetích stran.
  • Firefox přichází s „černou listinou“ domén třetích stran, kde blokuje soubory cookie třetích stran.
Poznámka:

Pokud načteme skript z domény třetí strany, například <script src="https://google-analytics.com/analytics.js"> a tento skript používá document.cookie nastavit cookie, pak takový cookie není třetí stranou.

Pokud skript nastaví cookie, pak bez ohledu na to, odkud skript pochází – cookie patří do domény aktuální webové stránky.

Příloha:GDPR

Toto téma vůbec nesouvisí s JavaScriptem, jen je třeba mít na paměti při nastavování cookies.

V Evropě existuje legislativa zvaná GDPR, která prosazuje soubor pravidel pro webové stránky, aby respektovaly soukromí uživatelů. Jedním z těchto pravidel je vyžadovat od uživatele výslovné povolení ke sledování souborů cookie.

Upozorňujeme, že jde pouze o sledování/identifikaci/autorizaci souborů cookie.

Pokud tedy nastavíme soubor cookie, který pouze ukládá nějaké informace, ale nesleduje ani neidentifikuje uživatele, můžeme to udělat.

Pokud ale chceme nastavit soubor cookie s ověřovací relací nebo ID sledování, musí to uživatel povolit.

Webové stránky mají obecně dvě varianty dodržování GDPR. Určitě jste je oba už viděli na webu:

  1. Pokud chce web nastavit sledovací soubory cookie pouze pro ověřené uživatele.

    Chcete-li tak učinit, registrační formulář by měl obsahovat zaškrtávací políčko jako „přijmout zásady ochrany osobních údajů“ (které popisuje, jak jsou soubory cookie používány), uživatel jej musí zaškrtnout a web pak může volně nastavit soubory cookie pro ověřování.

  2. Pokud chce web nastavit sledovací soubory cookie pro každého.

    Aby to bylo legální, webová stránka zobrazuje modální „úvodní obrazovku“ pro nováčky a vyžaduje, aby souhlasili s cookies. Pak je může web nastavit a umožnit lidem vidět obsah. To však může být pro nové návštěvníky znepokojivé. Nikdo nemá rád, když se místo obsahu zobrazují takové modální úvodní obrazovky, které je třeba kliknout. GDPR však vyžaduje výslovnou dohodu.

GDPR se netýká pouze souborů cookie, ale také dalších problémů souvisejících s ochranou soukromí, ale to je příliš mimo náš rozsah.

Shrnutí

document.cookie poskytuje přístup k souborům cookie.

  • Operace zápisu upravují pouze soubory cookie v nich uvedené.
  • Název/hodnota musí být zakódována.
  • Velikost jednoho souboru cookie nesmí přesáhnout 4 kB. Počet povolených souborů cookie v doméně je přibližně 20+ (liší se podle prohlížeče).

Možnosti souborů cookie:

  • path=/ , ve výchozím nastavení aktuální cesta, zviditelní soubor cookie pouze pod touto cestou.
  • domain=site.com , ve výchozím nastavení je soubor cookie viditelný pouze v aktuální doméně. Pokud je doména nastavena explicitně, soubor cookie bude viditelný na subdoménách.
  • expires nebo max-age nastavuje dobu vypršení platnosti cookie. Bez nich cookie při zavření prohlížeče zemře.
  • secure vytvoří cookie pouze HTTPS.
  • samesite zakazuje prohlížeči posílat soubory cookie s požadavky přicházejícími mimo web. To pomáhá předcházet útokům XSRF.

Navíc:

  • Soubory cookie třetích stran může prohlížeč zakázat, např. Safari to dělá ve výchozím nastavení.
  • Při nastavování sledovacího souboru cookie pro občany EU vyžaduje GDPR požádat o povolení.