Java Academy · Oppitunti

JWT: rakenne, luonti ja varmennus

Pura JWT:n rakenne manuaalisesti, luo salaisuudella allekirjoitettuja tokeneita ja varmista claimit ilman frameworkeja.

Oppitunti 4/413 vaihetta

JWT: rakenne, luonti ja varmennus on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mikä JWT on

JSON Web Token (JWT) on tiivis ja URL-ystävällinen token-muoto claimien välittämiseen osapuolten välillä. JWT allekirjoitetaan ja se voidaan myös salata. Se on itsenäinen — claimien tarkistamiseen ei tarvita tietokantahakua.

JWT:n rakenne: Header.Payload.Signature

JWT koostuu kolmesta pisteillä erotetusta Base64URL-koodatusta osasta: header.payload.signature. Header määrittää algoritmin. Payload sisältää claimit. Allekirjoitus varmistaa eheyden.

// Example JWT:
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9      <- header
// .eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0  <- payload
// .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c     <- signature

Dekoodattu header ja payload

Dekoodatkaa kukin osa Base64URL-muodosta nähdäksenne JSON-sisällön. Payload sisältää ”claimit” — yleisiä claim-arvoja ovat sub (kohde), iss (myöntäjä), exp (vanheneminen) ja iat (myöntämisaika).

// Header:
{ "alg": "HS256", "typ": "JWT" }
// Payload:
{ "sub": "user-42", "name": "Alice", "role": "ADMIN",
  "iat": 1716000000, "exp": 1716003600 }

JWT:n luominen manuaalisesti (HS256)

Muodostakaa headerin ja payloadin JSON, koodatkaa kumpikin Base64URL-muotoon, yhdistäkää ne pisteellä, laskekaa sitten HMAC-SHA256 arvosta header.payload ja lisätkää tulos allekirjoitukseksi.

String header  = Base64.getUrlEncoder().withoutPadding()
    .encodeToString("{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes());
String payload = Base64.getUrlEncoder().withoutPadding()
    .encodeToString("{\"sub\":\"user-42\",\"exp\":9999999999}".getBytes());
String sigInput = header + "." + payload;
byte[] sig = computeHmac(secretKey, sigInput);
String jwt = sigInput + "." + Base64.getUrlEncoder().withoutPadding().encodeToString(sig);

JWT:n tarkistaminen manuaalisesti

Jakakaa tunniste pisteiden kohdalta, dekoodatkaa header ja payload, laskekaa HMAC uudelleen arvosta header.payload, verratkaa sitä allekirjoitukseen ja tarkistakaa, että exp on tulevaisuudessa.

String[] parts = jwt.split("\\.");
String sigInput = parts[0] + "." + parts[1];
byte[] expectedSig = computeHmac(secretKey, sigInput);
byte[] actualSig   = Base64.getUrlDecoder().decode(parts[2]);
if (!MessageDigest.isEqual(expectedSig, actualSig)) throw new SecurityException("Invalid signature");
// Decode payload and check exp:
String payloadJson = new String(Base64.getUrlDecoder().decode(parts[1]));
// parse JSON and check exp > now

java-jwt-kirjaston käyttäminen (Auth0)

com.auth0:java-jwt-kirjasto yksinkertaistaa JWT-tunnisteiden luomista ja tarkistamista ketjutettavan rajapinnan avulla.

// Create:
Algorithm alg = Algorithm.HMAC256(secretKey);
String token = JWT.create()
    .withSubject("user-42")
    .withClaim("role", "ADMIN")
    .withExpiresAt(Instant.now().plusSeconds(3600))
    .sign(alg);
// Verify:
JWTVerifier verifier = JWT.require(alg).withIssuer("my-service").build();
DecodedJWT decoded = verifier.verify(token);
System.out.println(decoded.getSubject());

HS256 ja RS256

HS256 käyttää jaettua symmetristä avainta — se on yksinkertainen, mutta sekä myöntäjän että tarkistajan on voitava luottaa toisiinsa avaimen suhteen. RS256 käyttää RSA:ta: allekirjoitus tehdään yksityisellä avaimella ja tarkistetaan julkisella avaimella — se sopii usean palvelun arkkitehtuureihin, joissa mikä tahansa palvelu voi tarkistaa allekirjoituksen tuntematta allekirjoitusavainta.

JWT-tunnisteiden tallentaminen: HttpOnly-evästeet ja localStorage

Tallentakaa JWT-tunnisteet HttpOnly-evästeisiin (JavaScript ei pääse niihin käsiksi, mikä estää XSS-varkaudet) ja käyttäkää Secure- sekä SameSite=Strict-lippuja. Välttäkää localStoragea — XSS-hyökkäykset voivat lukea sen sisällön.

// Set JWT as HttpOnly cookie in Spring:
ResponseCookie cookie = ResponseCookie.from("jwt", token)
    .httpOnly(true).secure(true).sameSite("Strict")
    .path("/").maxAge(3600).build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());

Päivitystunnisteet

JWT-tunnisteilla on lyhyt voimassaoloaika (15 minuuttia). Päivitystunnisteet ovat läpinäkymättömiä, ja ne tallennetaan palvelimelle; niiden voimassaoloaika on pidempi. Asiakas vaihtaa päivitystunnisteen uuteen JWT-tunnisteeseen ilman uutta todennusta.

JWT:n mitätöinnin haaste

JWT-tunnisteet ovat tilattomia — niissä ei ole sisäänrakennettua mitätöintiä. Käyttäkää lyhyttä voimassaoloaikaa ja Redisissä olevaa mitätöityjen JWT-tunnisteiden tunnisteiden estolistaa (jti-claim), jotta uloskirjautuminen voidaan toteuttaa ennen tunnisteen vanhenemista.

// On logout, add the jti to a Redis blocklist with TTL = token expiry:
redis.set("revoked:" + jti, "1", ex, 3600);
// On verify, check blocklist:
if (redis.exists("revoked:" + decoded.getId())) throw new SecurityException("Token revoked");

JWT-integraatio Spring Securityssä

Toteuttakaa Spring Securityssä JwtAuthenticationFilter extends OncePerRequestFilter -suodatin, joka poimii JWT-tunnisteen, tarkistaa sen ja asettaa SecurityContext-kontekstin sen perusteella jokaisen pyynnön yhteydessä.

String token = request.getHeader("Authorization").replace("Bearer ","");
DecodedJWT decoded = verifier.verify(token);
String userId = decoded.getSubject();
UsernamePasswordAuthenticationToken auth =
    new UsernamePasswordAuthenticationToken(userId, null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);

Pikatarkistus

Mikä on keskeinen rakenteellinen ero HS256- ja RS256-JWT-allekirjoitusten välillä?

Kertaus

JWT = header.payload.signature (Base64URL). Allekirjoittakaa HMACilla (HS256) tai RSA:lla (RS256). Tarkistakaa allekirjoitus ja exp-claim. Tallentakaa tunnisteet HttpOnly-evästeisiin. Käyttäkää lyhyttä voimassaoloaikaa ja päivitystunnisteita. Mitätöikää tunnisteet Redisissä olevan jti-estolistan avulla.

Aloita maksutta

Opi Java tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
104
Oppitunnit
374

Usein kysytyt kysymykset

Onko oppitunti ”JWT: rakenne, luonti ja varmennus” ilmainen?

Kyllä – oppitunnin ”JWT: rakenne, luonti ja varmennus” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”JWT: rakenne, luonti ja varmennus”?

Pura JWT:n rakenne manuaalisesti, luo salaisuudella allekirjoitettuja tokeneita ja varmista claimit ilman frameworkeja. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”JWT: rakenne, luonti ja varmennus”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?

Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Kryptografinen tiivistys MessageDigestilla
  2. AES-salauksella toteutettu symmetrinen salaus
  3. HMAC-SHA256 viestin eheyden varmistamiseen
  4. JWT: rakenne, luonti ja varmennus
← Takaisin: Java Academy