0Pricing
Java Academy · レッスン

JWT:構造、生成、検証

JWTの構造を手動でデコードし、秘密鍵で署名付きトークンを作成して、フレームワークを使わずにクレームを検証します。

「JWT:構造、生成、検証」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

JWT とは

JSON Web Token(JWT)は、当事者間でクレームを送信するための、コンパクトで URL セーフなトークン形式です。JWT には署名が付けられ、必要に応じて暗号化もされます。自己完結型であるため、クレームの検証にデータベース照会は必要ありません。

JWT の構造: Header.Payload.Signature

JWT は、ドットで区切られた 3 つの Base64URL エンコード部分で構成されます。header.payload.signature の形式です。ヘッダーにはアルゴリズムが指定され、ペイロードにはクレームが含まれます。署名によって完全性を検証します。

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

デコードしたヘッダーとペイロード

各部分を Base64URL でデコードすると、JSON を確認できます。ペイロードにはクレームが含まれます。標準的なクレームには、sub(サブジェクト)、iss(発行者)、exp(有効期限)、iat(発行時刻)があります。

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

JWT を手動で作成する(HS256)

ヘッダーとペイロードの JSON を作成し、それぞれを Base64URL エンコードしてドットで連結します。次に、header.payload に対して HMAC-SHA256 を計算し、署名として末尾に追加します。

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 を手動で検証する

ドットで分割し、ヘッダーとペイロードをデコードします。header.payload に対して HMAC を再計算し、署名と比較して、exp が未来の時刻であることを確認します。

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 ライブラリを使用する(Auth0)

com.auth0:java-jwt ライブラリを使用すると、流暢な API によって JWT の作成と検証を簡略化できます。

// 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 と RS256

HS256 は共有対称鍵を使用します。単純ですが、発行者と検証者の両方が鍵を信頼して共有する必要があります。RS256 は RSA を使用し、秘密鍵で署名して公開鍵で検証します。署名鍵を知らなくても各サービスが検証できるため、複数サービスのアーキテクチャに適しています。

JWT の保存: HttpOnly Cookie と localStorage

JWT は HttpOnly Cookie に保存します。JavaScript からアクセスできないため XSS による窃取を防止できます。Secure と SameSite=Strict フラグも設定してください。localStorage は避けてください。XSS 攻撃によって読み取られる可能性があります。

// 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());

リフレッシュトークン

JWT の有効期限は短く設定します(15 分)。リフレッシュトークン(不透明な値で、サーバー側に保存)は、より長い有効期限を持ちます。クライアントは再認証せずに、リフレッシュトークンを新しい JWT と交換します。

JWT の失効に関する課題

JWT はステートレスであり、組み込みの失効機能はありません。有効期限を短く設定し、Redis に失効した JWT ID(jti クレーム)のブロックリストを保持して、有効期限前のログアウトに対応します。

// 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");

Spring Security での JWT 統合

Spring Security では、JwtAuthenticationFilter extends OncePerRequestFilter を実装して、各リクエストで JWT を取り出して検証し、SecurityContext に設定します。

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);

確認問題

HS256 と RS256 の JWT 署名における、鍵の構造上の違いは何ですか。

まとめ

JWT は header.payload.signature(Base64URL)で構成されます。HMAC(HS256)または RSA(RS256)で署名します。署名と exp クレームを検証します。HttpOnly Cookie に保存します。有効期限を短く設定し、リフレッシュトークンを使用します。Redis の jti ブロックリストで失効させます。

よくある質問

「JWT:構造、生成、検証」レッスンは無料ですか?

はい。「JWT:構造、生成、検証」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「JWT:構造、生成、検証」で何を学びますか?

JWTの構造を手動でデコードし、秘密鍵で署名付きトークンを作成して、フレームワークを使わずにクレームを検証します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「JWT:構造、生成、検証」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. MessageDigestによる暗号学的ハッシュ
  2. AES共通鍵暗号
  3. メッセージ完全性のためのHMAC-SHA256
  4. JWT:構造、生成、検証
← Java Academyに戻る