JWT vs istunto: minkä todennusmekanismin valita?
Käyttäjän todentaminen tarkoittaa sen tietämistä joka pyynnöllä, kuka hän on. Vastakkain on kaksi suurta perhettä: palvelinistunnot, joissa palvelin pitää kirjaa kirjautuneesta käyttäjästä, ja JSON Web Tokenit (JWT), joissa identiteetti kulkee asiakkaan kantamassa allekirjoitetussa tokenissa. Valinta vaikuttaa turvallisuuteen, kuormituksen kasvattamiseen ja käyttäjän uloskirjaamisen helppouteen. Näin teet päätöksen tilanteesi mukaan.
Palvelinistunnot (stateful)
Istunnossa palvelin luo istuntotunnisteen kirjautumisen yhteydessä, tallentaa siihen liittyvät tiedot (identiteetti, roolit, ostoskori) palvelimen puolelle (muisti, Redis, tietokanta) ja palauttaa selaimelle evästeen, joka sisältää vain tämän tunnisteen. Joka pyynnöllä palvelin lukee evästeen, löytää istunnon ja tietää, kuka puhuu.
- Tila palvelimen puolella: totuuden lähde pysyy palvelimella, asiakas kantaa vain läpinäkymätöntä viittausta.
- Välitön peruutus: istunnon poistaminen palvelimen puolelta kirjaa käyttäjän ulos välittömästi.
- Eväste: selaimen automaattisesti välittämä, ihanteellisesti
HttpOnly,SecurejaSameSite-attribuuteilla.
JSON Web Tokenit (stateless)
JWT on itsekantava token, joka koostuu kolmesta base64url-koodatusta ja pisteillä erotetusta osasta: header, payload (claimit, esimerkiksi käyttäjätunniste ja vanheneminen) ja allekirjoitus. Palvelin allekirjoittaa tokenin kirjautumisen yhteydessä; sen jälkeen sille riittää allekirjoituksen tarkistaminen luottaakseen sisältöön, mitään tallentamatta.
- Tilaton: kaikki tarvittava tieto on tokenissa, palvelin ei tarvitse jaettua muistia.
- Tarkistettavissa kaikkialla: mikä tahansa avaimen tunteva palvelu voi validoida tokenin, kätevää hajautetuille arkkitehtuureille ja SSO:lle.
- Työkalut: voit tarkastella tokenia JWT-dekooderillamme, tarkistaa sen allekirjoituksen JWT-vahvistimella tai luoda sellaisen JWT-generaattorilla.
Vertailutaulukko
| Kriteeri | Palvelinistunto | JWT |
|---|---|---|
| Tila | Stateful (tallennettu palvelimelle) | Stateless (asiakkaan kantama) |
| Palvelimen tallennus | Vaaditaan (Redis, tietokanta) | Ei mitään |
| Peruutus | Välitön | Vaikea ennen vanhenemista |
| Vaakaskaalautuvuus | Vaatii jaetun säilön | Natiivi |
| Välitetty koko | Pieni (yksi tunniste) | Suurempi (allekirjoitetut claimit) |
| Verkkotunnusten välinen / SSO | Hankala | Sopiva |
| XSS-pinta | Matala, jos HttpOnly-eväste | Korkea, jos tallennettu localStorageen |
Turvallisuus: XSS, CSRF ja peruutus
Molemmat lähestymistavat ovat turvallisia, jos ne on toteutettu hyvin, mutta niiden riskit eroavat.
- XSS:
HttpOnly-istuntoeväste on JavaScriptin ulottumattomissa, joten se on suojattu injektiolla tapahtuvalta varkaudelta.localStorageentallennettu JWT on sen sijaan minkä tahansa skriptin luettavissa, mikä tekee siitä houkuttelevan kohteen. JWT:n tallentaminenHttpOnly-evästeeseen kumoaa tämän JWT:n edun mutta tuo takaisin CSRF-riskin. - CSRF: evästeet lähetetään automaattisesti, joten ne ovat alttiita CSRF:lle ilman suojausta (
SameSite-attribuutti, CSRF-suojaustoken). ManuaalisestiAuthorization-otsakkeessa lähetettyä JWT:tä tämä ei koske. - Peruutus: tämä on JWT:n heikko kohta. Koska se on itsekantava, sitä ei voi mitätöidä ennen vanhenemista ilman palvelintilan takaisin tuomista (peruutuslista, estolista). Istunto poistetaan välittömästi.
Skaalautuvuus ja arkkitehtuuri
Yhdellä palvelimella istunnot ovat triviaaleja. Heti kun jaat kuorman useiden instanssien kesken, jokaisen instanssin on päästävä istuntoihin käsiksi: tarvitaan jaettu säilö (Redis) tai sticky-istunnot. JWT loistaa tässä, sillä mikä tahansa instanssi validoi tokenin ilman verkkokutsua tai yhteistä tallennusta.
- Mikropalvelut: JWT levittää identiteetin palvelusta toiseen ilman keskitettyä tietokantaa.
- Julkiset ja mobiili-API:t: JWT välttää evästeiden hallinnan natiiviasiakkaan puolella.
- Klassinen monoliitti: istunto pysyy oletuksena yksinkertaisempana ja turvallisempana.
Milloin valita kumpi
Valitse istunnot, kun
- Kehität klassista verkkosovellusta palvelinpuolen renderöinnillä
- Välitön peruutus on kriittinen (pankki, terveydenhuolto, back-office)
- Haluat oletuksena turvallisimman ratkaisun, jossa on vähiten sudenkuoppia
- Infrastruktuurisi kestää jaetun istuntosäilön vaivatta
Valitse JWT, kun
- Julkaiset API:n, jota käyttävät SPA:t, mobiili tai kolmannet osapuolet
- Sinulla on mikropalveluarkkitehtuuri tai verkkotunnusten välinen SSO
- Sinun on skaalauduttava vaakasuunnassa ilman jaettua säilöä
- Hyväksyt lyhyen vanhenemisen ja tokenien uusimisen hallinnan
Suositus
Suurimmalle osalle verkkosovelluksista palvelinistunnot pysyvät turvallisimpana ja yksinkertaisimpana valintana: välitön peruutus, HttpOnly-eväste ja nolla tokenien hallintaa asiakkaan puolella. Varaa JWT tapauksiin, joissa sen tilattomuus tuo todellista arvoa: tilaton API, mobiili, mikropalvelut, SSO.
Jos valitset JWT:n, pidä lyhyt elinikä (muutama minuutti) yhdistettynä refresh-tokeniin, joka on tallennettu HttpOnly-evästeeseen, ja varaudu peruutuslistalla arkaluonteisia tapauksia varten. Näin yhdistät molempien maailmojen parhaat puolet.
Usein kysytyt kysymykset
Onko JWT salattu?
Ei, oletuksena JWT on vain allekirjoitettu, ei salattu. Sen payload on base64url-koodattu ja kenen tahansa sen sieppaavan luettavissa. Älä koskaan laita arkaluonteisia tietoja selkokielisenä JWT:hen. Sisällön salaamiseksi on käytettävä JWE:tä (JSON Web Encryption).
Minne JWT tallennetaan asiakkaan puolella?
Turvallisin on HttpOnly, Secure ja SameSite -eväste, joka suojaa XSS:llä tapahtuvalta varkaudelta. localStorage on yksinkertaisempi mutta altistaa tokenin mille tahansa haitalliselle skriptille. Vältä sitä korkean käyttöoikeuden tokeneille.
Miten käyttäjä kirjataan ulos JWT:llä?
Koska token on itsekantava, todellinen uloskirjautuminen vaatii joko sen vanhenemisen odottamista tai peruutuslistan ylläpitämistä palvelimen puolella. Siksi käytetään lyhyitä elinikiä ja refresh-tokenia, joka voidaan peruuttaa.
Voiko istuntoja ja JWT:tä yhdistää?
Kyllä, se on yleinen käytäntö: lyhytikäinen JWT-access-token API-kutsuille ja istuntona hallittu refresh-token (tallennettu ja peruutettavissa palvelimen puolella) access-tokenin uusimiseen.