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, Secure ja SameSite atribuutidega.

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
OlekStateful (salvestatud serverisse)Stateless (kliendi kantud)
Serveripoolne salvestusNõutav (Redis, andmebaas)Puudub
TühistamineKoheneRaske enne aegumist
Horisontaalne skaleeritavusVajab jagatud salvestustNatiivne
Edastatav suurusVäike (üks identifikaator)Suurem (allkirjastatud claim'id)
Domeenideülene / SSOTülikasSobiv
XSS-i pindMadal, kui HttpOnly küpsisKõ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: HttpOnly sessioonikü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 salvestamine HttpOnly kü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 (SameSite atribuut, CSRF-vastane token). Käsitsi Authorization pä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.