JWT vs sessioon: millise autentimismehhanismi valida?
Kasutaja autentimine tähendab igal päringul teadmist, kes ta on. Vastamisi seisavad kaks suurt perekonda: serveripoolsed sessioonid, kus server hoiab arvet sisselogitud kasutaja kohta, ja JSON Web Token'id (JWT), kus identiteet rändab kliendi kantud allkirjastatud tokenis. Valik mõjutab turvalisust, koormuse kasvatamise võimet ja kasutaja väljalogimise lihtsust. Vaatame, kuidas otsustada vastavalt sinu kontekstile.
Serveripoolsed sessioonid (stateful)
Sessiooni puhul loob server sisselogimisel sessiooni identifikaatori, salvestab seotud andmed (identiteet, rollid, ostukorv) serveri poolel (mälu, Redis, andmebaas) ja saadab brauserile küpsise, mis sisaldab ainult seda identifikaatorit. Igal päringul loeb server küpsise, leiab sessiooni ja teab, kes räägib.
- Olek serveri poolel: tõe allikas jääb serverisse, klient kannab vaid läbipaistmatut viidet.
- Kohene tühistamine: sessiooni kustutamine serveri poolel logib kasutaja koheselt välja.
- Küpsis: brauseri poolt automaatselt edastatud, ideaalis
HttpOnly,SecurejaSameSiteatribuutidega.
JSON Web Token'id (stateless)
JWT on isekandev token, mis koosneb kolmest base64url-kodeeritud ja punktidega eraldatud osast: header, payload (claim'id, näiteks kasutaja identifikaator ja aegumine) ja allkiri. Server allkirjastab tokeni sisselogimisel; seejärel piisab tal sisu usaldamiseks vaid allkirja kontrollimisest, midagi salvestamata.
- Olekuta: kogu vajalik info on tokenis, server ei vaja jagatud mälu.
- Igal pool kontrollitav: iga teenus, kes võtit teab, saab tokeni valideerida, mugav hajutatud arhitektuuride ja SSO jaoks.
- Tööriistad: saad tokenit uurida meie JWT dekoodriga, kontrollida selle allkirja JWT verifitseerijaga või luua sellise JWT generaatoriga.
Võrdlustabel
| Kriteerium | Serveripoolne sessioon | JWT |
|---|---|---|
| Olek | Stateful (salvestatud serverisse) | Stateless (kliendi kantud) |
| Serveripoolne salvestus | Nõutav (Redis, andmebaas) | Puudub |
| Tühistamine | Kohene | Raske enne aegumist |
| Horisontaalne skaleeritavus | Vajab jagatud salvestust | Natiivne |
| Edastatav suurus | Väike (üks identifikaator) | Suurem (allkirjastatud claim'id) |
| Domeenideülene / SSO | Tülikas | Sobiv |
| XSS-i pind | Madal, kui HttpOnly küpsis | Kõrge, kui salvestatud localStorage'isse |
Turvalisus: XSS, CSRF ja tühistamine
Mõlemad lähenemised on turvalised, kui need on hästi rakendatud, kuid nende riskid erinevad.
- XSS:
HttpOnlysessiooniküpsis on JavaScriptile kättesaamatu, seega kaitstud süstimise teel varguse eest.localStorage'isse salvestatud JWT on seevastu loetav igale skriptile, mis teeb sellest eelistatud sihtmärgi. JWT salvestamineHttpOnlyküpsisesse tühistab selle JWT eelise, kuid toob taas sisse CSRF-i riski. - CSRF: küpsised saadetakse automaatselt, seega on need kaitseta haavatavad CSRF-i suhtes (
SameSiteatribuut, CSRF-vastane token). KäsitsiAuthorizationpäisesse saadetud JWT-d see ei puuduta. - Tühistamine: see on JWT nõrk koht. Kuna see on isekandev, ei saa seda enne aegumist kehtetuks muuta ilma serveri oleku taastoomiseta (tühistusnimekiri, must nimekiri). Sessioon kustutatakse koheselt.
Skaleeritavus ja arhitektuur
Ühe serveriga on sessioonid triviaalsed. Niipea, kui jaotad koormuse mitme instantsi vahel, peab iga instants sessioonidele ligi pääsema: vaja on jagatud salvestust (Redis) või sticky sessioone. JWT särab siin, sest iga instants valideerib tokeni ilma võrgukõne ega ühise salvestuseta.
- Mikroteenused: JWT levitab identiteeti ühest teenusest teise ilma keskse andmebaasita.
- Avalikud ja mobiili-API-d: JWT väldib küpsiste haldamist natiivse kliendi poolel.
- Klassikaline monoliit: sessioon jääb vaikimisi lihtsamaks ja turvalisemaks.
Millal kumba valida
Vali sessioonid, kui
- Arendad klassikalist veebirakendust serveripoolse renderdamisega
- Kohene tühistamine on kriitiline (pangandus, tervishoid, back-office)
- Soovid vaikimisi kõige turvalisemat lahendust kõige väiksema arvu lõksudega
- Sinu taristu kannab jagatud sessioonisalvestust valutult
Vali JWT, kui
- Avaldad API-d, mida tarbivad SPA-d, mobiil või kolmandad osapooled
- Sul on mikroteenuste arhitektuur või domeenidevaheline SSO
- Pead horisontaalselt skaleeruma ilma jagatud salvestuseta
- Nõustud haldama lühikest aegumist ja tokenite värskendamist
Soovitus
Enamiku veebirakenduste jaoks jäävad serveripoolsed sessioonid kõige turvalisemaks ja lihtsamaks valikuks: kohene tühistamine, HttpOnly küpsis ja null tokenihaldust kliendi poolel. Jäta JWT juhtudeks, kus selle olekupuudus annab tõelist väärtust: stateless API, mobiil, mikroteenused, SSO.
Kui valid JWT, hoia lühike eluiga (mõni minut) koos refresh-tokeniga, mis on salvestatud HttpOnly küpsisesse, ja näe tundlike juhtude jaoks ette tühistusnimekiri. Nii ühendad mõlema maailma parima.
Korduma kippuvad küsimused
Kas JWT on krüpteeritud?
Ei, vaikimisi on JWT ainult allkirjastatud, mitte krüpteeritud. Selle payload on base64url-kodeeritud ja loetav igaühele, kes selle pealt kuulab. Ära kunagi pane tundlikke andmeid avatekstina JWT sisse. Sisu krüpteerimiseks tuleb kasutada JWE-d (JSON Web Encryption).
Kuhu JWT kliendi poolel salvestada?
Kõige turvalisem on HttpOnly, Secure ja SameSite küpsis, mis kaitseb XSS-i kaudu varguse eest. localStorage on lihtsam, kuid avab tokeni igale pahatahtlikule skriptile. Väldi seda kõrge õigustasemega tokenite puhul.
Kuidas logida kasutaja JWT-ga välja?
Kuna token on isekandev, nõuab tegelik väljalogimine kas selle aegumise ootamist või tühistusnimekirja pidamist serveri poolel. Seetõttu kasutatakse lühikesi elueasid ja refresh-tokenit, mida saab tühistada.
Kas sessioone ja JWT-d saab kombineerida?
Jah, see on levinud praktika: lühikese elueaga JWT access-token API-kõnede jaoks ja sessioonina hallatav refresh-token (salvestatud ja tühistatav serveri poolel) access-tokeni uuendamiseks.