JWT vs Sesija: koji mehanizam autentifikacije odabrati?

Autentificirati korisnika znači znati pri svakom zahtjevu tko je on. Dvije velike obitelji se nadmeću: poslužiteljske sesije, gdje poslužitelj čuva trag prijavljenog korisnika, i JSON Web Tokeni (JWT), gdje identitet putuje u potpisanom tokenu koji nosi klijent. Izbor utječe na sigurnost, sposobnost skaliranja i lakoću odjave korisnika. Evo kako odlučiti ovisno o vašem kontekstu.

Poslužiteljske sesije (sa stanjem)

Sa sesijom poslužitelj stvara identifikator sesije pri prijavi, pohranjuje povezane podatke (identitet, uloge, košarica) na strani poslužitelja (memorija, Redis, baza podataka) i vraća pregledniku kolačić koji sadrži samo taj identifikator. Pri svakom zahtjevu poslužitelj čita kolačić, pronalazi sesiju i zna tko govori.

  • Stanje na strani poslužitelja: izvor istine ostaje na poslužitelju, klijent nosi samo neprozirnu referencu.
  • Trenutni opoziv: brisanje sesije na strani poslužitelja trenutno odjavljuje korisnika.
  • Kolačić: preglednik ga prenosi automatski, idealno kao HttpOnly, Secure i SameSite.

JSON Web Tokeni (bez stanja)

JWT je samonoseći token sastavljen od tri dijela kodirana u base64url i odvojena točkama: header, payload (claims, na primjer identifikator korisnika i istek) i potpis. Poslužitelj potpisuje token pri prijavi; nakon toga mu je dovoljno provjeriti potpis kako bi vjerovao sadržaju, bez pohranjivanja ičega.

  • Bez stanja: sve potrebne informacije su u tokenu, poslužitelju nije potrebna dijeljena memorija.
  • Provjerljiv svugdje: bilo koja usluga koja zna ključ može validirati token, što je praktično za distribuirane arhitekture i SSO.
  • Alati: token možete pregledati našim JWT dekoderom, provjeriti njegov potpis JWT verifikatorom ili ga izraditi JWT generatorom.

Usporedna tablica

Kriterij Poslužiteljska sesija JWT
StanjeSa stanjem (pohranjeno na poslužitelju)Bez stanja (nosi ga klijent)
Pohrana na poslužiteljuPotrebna (Redis, baza)Nikakva
OpozivTrenutniTežak prije isteka
Horizontalna skalabilnostPotreban dijeljeni spremnikIzvorna
Veličina prijenosaMala (jedan identifikator)Veća (potpisani claims)
Među-domenski / SSOOgraničavajućePrikladno
XSS površinaNiska s HttpOnly kolačićemVisoka ako je u localStorage

Sigurnost: XSS, CSRF i opoziv

Oba pristupa su sigurna ako su dobro implementirana, ali se njihovi rizici razlikuju.

  • XSS: HttpOnly kolačić sesije nedostupan je JavaScriptu, stoga je zaštićen od krađe ubacivanjem. JWT pohranjen u localStorage, naprotiv, čitljiv je svakoj skripti, što ga čini privlačnom metom. Pohrana JWT-a u HttpOnly kolačić poništava tu prednost JWT-a, ali ponovno uvodi rizik CSRF-a.
  • CSRF: kolačići se šalju automatski, stoga su ranjivi na CSRF bez zaštite (atribut SameSite, anti-CSRF token). JWT poslan ručno u zaglavlju Authorization nije pogođen.
  • Opoziv: to je slaba točka JWT-a. Budući da je samonoseći, ne može se poništiti prije isteka bez ponovnog uvođenja stanja poslužitelja (popis opoziva, crna lista). Sesija se briše trenutno.

Skalabilnost i arhitektura

Na jednom poslužitelju sesije su trivijalne. Čim raspodijelite opterećenje na više instanci, svaka instanca mora pristupiti sesijama: potreban je dijeljeni spremnik (Redis) ili sticky sessions. JWT ovdje blista, jer bilo koja instanca validira token bez mrežnog poziva ili zajedničke pohrane.

  • Mikroservisi: JWT prenosi identitet s jedne usluge na drugu bez središnje baze.
  • Javni i mobilni API-ji: JWT izbjegava upravljanje kolačićima na strani izvornog klijenta.
  • Klasični monolit: sesija ostaje jednostavnija i sigurnija prema zadanim postavkama.

Kada odabrati jedno ili drugo

Odaberite sesije kada

  • Razvijate klasičnu web aplikaciju s poslužiteljskim renderiranjem
  • Trenutni opoziv je kritičan (banka, zdravstvo, back-office)
  • Želite najsigurnije rješenje prema zadanim postavkama, s najmanje zamki
  • Vaša infrastruktura bez problema podnosi dijeljeni spremnik sesija

Odaberite JWT kada

  • Izlažete API koji konzumiraju SPA-ovi, mobilni uređaji ili treće strane
  • Imate mikroservisnu arhitekturu ili SSO između domena
  • Morate skalirati horizontalno bez dijeljenog spremnika
  • Prihvaćate upravljanje kratkim istekom i osvježavanjem tokena

Preporuka

Za većinu web aplikacija poslužiteljske sesije ostaju najsigurniji i najjednostavniji izbor: trenutni opoziv, HttpOnly kolačić i nikakvo upravljanje tokenom na strani klijenta. Zadržite JWT za slučajeve u kojima njegova bezstatnost donosi stvarnu vrijednost: API bez stanja, mobilni uređaji, mikroservisi, SSO.

Ako se odlučite za JWT, zadržite kratak vijek trajanja (nekoliko minuta) u kombinaciji s refresh tokenom pohranjenim u HttpOnly kolačiću i predvidite popis opoziva za osjetljive slučajeve. Tada kombinirate najbolje iz oba svijeta.

Često postavljana pitanja

Je li JWT šifriran?

Ne, prema zadanim postavkama JWT je samo potpisan, ne šifriran. Njegov payload je kodiran u base64url i čitljiv svakome tko ga presretne. Nikada ne stavljajte osjetljive podatke u čitljivom obliku u JWT. Za šifriranje sadržaja potrebno je pribjeći JWE (JSON Web Encryption).

Gdje pohraniti JWT na strani klijenta?

Najsigurniji je HttpOnly, Secure i SameSite kolačić, koji štiti od krađe putem XSS-a. localStorage je jednostavniji, ali izlaže token svakoj zlonamjernoj skripti. Izbjegavajte ga za tokene s visokim ovlastima.

Kako odjaviti korisnika s JWT-om?

Budući da je token samonoseći, stvarna odjava zahtijeva ili čekanje na njegov istek ili održavanje popisa opoziva na strani poslužitelja. Zato se koriste kratki vijekovi trajanja i refresh token koji se može opozvati.

Mogu li se kombinirati sesije i JWT?

Da, to je uobičajena praksa: JWT access token kratkog vijeka trajanja za API pozive i refresh token kojim se upravlja poput sesije (pohranjen i opoziv na strani poslužitelja) za obnavljanje access tokena.