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:
- 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“. - 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. - 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 zaencodeURIComponent
, 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é jakosamesite
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:
-
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.
-
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:
-
Stránka na adrese
site.com
načte banner z jiného webu:<img src="https://ads.com/banner.png">
. -
Spolu s bannerem i vzdálený server na
ads.com
může nastavitSet-Cookie
záhlaví se souborem cookie jakoid=1234
. Takový soubor cookie pochází zads.com
domény a bude viditelný pouze naads.com
: -
Příště až
ads.com
při přístupu, vzdálený server obdržíid
cookie a rozpozná uživatele: -
Ještě důležitější je, když se uživatel přesune z
site.com
na jiný webother.com
, který má také banner, pakads.com
získá cookie, protože patří kads.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.
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:
-
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í.
-
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
nebomax-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í.