JWT pret sesiju: kuru autentifikācijas mehānismu izvēlēties?
Autentificēt lietotāju nozīmē katra pieprasījuma laikā zināt, kas viņš ir. Saduras divas lielas saimes: servera sesijas, kur serveris seko pieslēgtajam lietotājam, un JSON Web Token (JWT), kur identitāte ceļo klienta nestā parakstītā marķierī. Izvēle ietekmē drošību, mērogošanas spēju un lietotāja atvienošanas vieglumu. Lūk, kā izlemt atkarībā no jūsu konteksta.
Servera sesijas (stateful)
Izmantojot sesiju, serveris pieslēgšanās brīdī izveido sesijas identifikatoru, saglabā saistītos datus (identitāti, lomas, grozu) servera pusē (atmiņā, Redis, datubāzē) un atgriež pārlūkam sīkdatni, kas satur tikai šo identifikatoru. Katra pieprasījuma laikā serveris nolasa sīkdatni, atrod sesiju un zina, kas runā.
- Stāvoklis servera pusē: patiesības avots paliek serverī, klients nes tikai necaurspīdīgu atsauci.
- Tūlītēja atsaukšana: sesijas dzēšana servera pusē acumirklī atvieno lietotāju.
- Sīkdatne: pārlūks pārsūta automātiski, ideālā gadījumā ar
HttpOnly,SecureunSameSite.
JSON Web Token (stateless)
JWT ir pašnesošs marķieris, kas sastāv no trim base64url kodētām daļām, atdalītām ar punktiem: galvenes, lietderīgās slodzes (claim'iem, piemēram, lietotāja identifikatora un derīguma termiņa) un paraksta. Serveris paraksta marķieri pieslēgšanās brīdī; pēc tam tam pietiek pārbaudīt parakstu, lai uzticētos saturam, neko nesaglabājot.
- Bez stāvokļa: visa nepieciešamā informācija ir marķierī, serverim nav vajadzīga koplietota atmiņa.
- Pārbaudāms visur: jebkurš pakalpojums, kas zina atslēgu, var validēt marķieri, ērti sadalītām arhitektūrām un SSO.
- Rīki: marķieri varat pārbaudīt ar mūsu JWT dekodētāju, kontrolēt tā parakstu ar JWT verificētāju vai izveidot jaunu ar JWT ģeneratoru.
Salīdzinājuma tabula
| Kritērijs | Servera sesija | JWT |
|---|---|---|
| Stāvoklis | Stateful (saglabāts serverī) | Stateless (nes klients) |
| Glabāšana serverī | Nepieciešama (Redis, datubāze) | Nav |
| Atsaukšana | Tūlītēja | Sarežģīta pirms derīguma termiņa |
| Horizontāla mērogojamība | Nepieciešama koplietota krātuve | Dabiska |
| Pārsūtītais izmērs | Mazs (viens identifikators) | Lielāks (parakstīti claim'i) |
| Starpdomēnu / SSO | Ierobežojošs | Piemērots |
| XSS virsma | Zema, ja sīkdatne HttpOnly | Augsta, ja glabāts localStorage |
Drošība: XSS, CSRF un atsaukšana
Abas pieejas ir drošas, ja tās ir pareizi ieviestas, taču to riski atšķiras.
- XSS:
HttpOnlysesijas sīkdatne nav pieejama JavaScript, tāpēc aizsargāta no zādzības caur injekciju. JWT, kas glabātslocalStorage, savukārt ir nolasāms jebkuram skriptam, kas padara to par iecienītu mērķi. JWT glabāšanaHttpOnlysīkdatnē anulē šo JWT priekšrocību, bet atkal ievieš CSRF risku. - CSRF: sīkdatnes tiek nosūtītas automātiski, tāpēc bez aizsardzības ievainojamas pret CSRF (
SameSiteatribūts, anti-CSRF marķieris). JWT, kas manuāli nosūtītsAuthorizationgalvenē, nav ietekmēts. - Atsaukšana: tā ir JWT vājā vieta. Tā kā tas ir pašnesošs, to nevar padarīt nederīgu pirms derīguma termiņa, neieviešot servera stāvokli (atsaukšanas sarakstu, melno sarakstu). Sesija tiek dzēsta acumirklī.
Mērogojamība un arhitektūra
Vienā serverī sesijas ir vienkāršas. Tiklīdz sadalāt slodzi pa vairākiem gadījumiem, katram gadījumam jāpiekļūst sesijām: vajadzīga koplietota krātuve (Redis) vai sticky sesijas. JWT šeit izceļas, jo jebkurš gadījums validē marķieri bez tīkla izsaukuma vai kopīgas glabāšanas.
- Mikropakalpojumi: JWT pārsūta identitāti no viena pakalpojuma uz citu bez centrālās datubāzes.
- Publiskas API un mobilās ierīces: JWT izvairās no sīkdatņu pārvaldības natīvā klienta pusē.
- Klasisks monolīts: sesija paliek vienkāršāka un drošāka pēc noklusējuma.
Kad izvēlēties vienu vai otru
Izvēlēties sesijas, kad
- Izstrādājat klasisku tīmekļa lietotni ar servera puses renderēšanu
- Tūlītēja atsaukšana ir kritiski svarīga (banka, veselība, back-office)
- Vēlaties drošāko risinājumu pēc noklusējuma, ar vismazāk slazdiem
- Jūsu infrastruktūra bez grūtībām notur koplietotu sesiju krātuvi
Izvēlēties JWT, kad
- Piedāvājat API, ko izmanto SPA, mobilās ierīces vai trešās puses
- Jums ir mikropakalpojumu arhitektūra vai SSO starp domēniem
- Jums jāmērogojas horizontāli bez koplietotas krātuves
- Piekrītat pārvaldīt īso derīguma termiņu un marķieru atjaunošanu
Ieteikums
Vairumam tīmekļa lietotņu servera sesijas paliek drošākā un vienkāršākā izvēle: tūlītēja atsaukšana, HttpOnly sīkdatne un nekādas marķieru pārvaldības klienta pusē. Rezervējiet JWT gadījumiem, kad tā bezstāvokļa daba sniedz patiesu vērtību: stateless API, mobilās ierīces, mikropakalpojumi, SSO.
Ja izvēlaties JWT, saglabājiet īsu derīguma termiņu (dažas minūtes) apvienojumā ar atsvaidzināšanas marķieri (refresh token), kas glabāts HttpOnly sīkdatnē, un paredziet atsaukšanas sarakstu jutīgiem gadījumiem. Tā jūs apvienojat labāko no abām pasaulēm.
Biežāk uzdotie jautājumi
Vai JWT ir šifrēts?
Nē, pēc noklusējuma JWT ir tikai parakstīts, nevis šifrēts. Tā lietderīgā slodze ir kodēta base64url un nolasāma ikvienam, kas to pārtver. Nekad nelieciet jutīgus datus atklātā tekstā JWT. Lai šifrētu saturu, jāizmanto JWE (JSON Web Encryption).
Kur glabāt JWT klienta pusē?
Visdrošākā ir HttpOnly, Secure un SameSite sīkdatne, kas aizsargā no zādzības caur XSS. localStorage ir vienkāršāks, bet pakļauj marķieri jebkuram ļaunprātīgam skriptam. Izvairieties no tā augsta privilēģiju līmeņa marķieriem.
Kā atvienot lietotāju ar JWT?
Tā kā marķieris ir pašnesošs, reāla atvienošana prasa vai nu gaidīt tā derīguma termiņa beigas, vai uzturēt atsaukšanas sarakstu servera pusē. Tāpēc izmanto īsus derīguma termiņus un atsvaidzināšanas marķieri, ko var atsaukt.
Vai var apvienot sesijas un JWT?
Jā, tā ir izplatīta prakse: īsa derīguma JWT piekļuves marķieris API izsaukumiem un atsvaidzināšanas marķieris, kas pārvaldīts kā sesija (glabāts un atsaucams servera pusē), lai atjaunotu piekļuves marķieri.