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, Secure ja SameSite -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
TilaStateful (tallennettu palvelimelle)Stateless (asiakkaan kantama)
Palvelimen tallennusVaaditaan (Redis, tietokanta)Ei mitään
PeruutusVälitönVaikea ennen vanhenemista
VaakaskaalautuvuusVaatii jaetun säilönNatiivi
Välitetty kokoPieni (yksi tunniste)Suurempi (allekirjoitetut claimit)
Verkkotunnusten välinen / SSOHankalaSopiva
XSS-pintaMatala, jos HttpOnly-evästeKorkea, 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. localStorageen tallennettu JWT on sen sijaan minkä tahansa skriptin luettavissa, mikä tekee siitä houkuttelevan kohteen. JWT:n tallentaminen HttpOnly-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). Manuaalisesti Authorization-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.