Play FrameworkでJWTとセッションを使い分け!Webアプリ認証の仕組みを徹底解説
生徒
「Play Frameworkでアプリを作っているのですが、ログイン機能を調べるとセッションやJWTという言葉が出てきて混乱しています。どちらを使えばいいのでしょうか?」
先生
「Webアプリの認証には、大きく分けてセッション方式とトークン方式(JWT)があります。Play Frameworkのセッションは少し特殊で、実は裏側でJWTと似た仕組みが使われているんですよ。」
生徒
「えっ、そうなんですか?似ているなら、なおさら違いが気になります。どうやって使い分けるのが正解ですか?」
先生
「通常のWeb画面ならセッション、スマホアプリや外部連携APIならJWTが向いています。それぞれのメリットと具体的な書き方を学んでいきましょう!」
1. Play Frameworkのセッションとは何か
Play Frameworkのセッションは、ユーザーの状態を一時的に保持するための仕組みです。 一般的なサーバーサイドフレームワーク(Servletなど)では、セッションデータをサーバーのメモリに保存しますが、Play Frameworkはステートレスな設計思想を持っています。 そのため、セッションデータは署名付きのクッキーとしてクライアント側のブラウザに保存されるのが大きな特徴です。
ブラウザがリクエストを送るたびにクッキーを送信するため、サーバー側で「誰がアクセスしてきたか」を判別できます。 改ざん検知のための署名が施されているため、ユーザーが勝手に中身を書き換えることはできません。 通常のWebサイトでログイン状態を維持する場合、このセッション機能を使うのが最も標準的で簡単な方法です。
2. JWTの基本構造とWeb認証での役割
JWTは「JSON Web Token」の略称で、情報をJSON形式で安全にやり取りするためのデータ規格です。 セッションと同じく認証に使われますが、最大の違いは「クッキー以外の場所にも保存できる」という点にあります。 例えば、スマホアプリのローカルストレージに保存したり、HTTPヘッダーに載せて送信したりすることが一般的です。
JWTは「ヘッダー」「ペイロード」「署名」の三つの部分で構成されており、情報の正当性を証明します。 Play FrameworkでAPIサーバーを構築し、フロントエンドがVue.jsやReact、あるいはiOS/Androidアプリである場合、このJWTを使った認証が非常に相性良く動作します。
3. Javaでセッションに値を保存する実装例
まずは、Play Frameworkの標準的なセッションを使ったログイン処理の実装を見てみましょう。
Javaのコントローラーでは、レスポンスに addingToSession を繋げるだけで簡単に値を保存できます。
このデータは自動的に署名付きクッキーとしてブラウザへ送られます。
package controllers;
import play.mvc.*;
public class SessionController extends Controller {
public Result login(Http.Request request) {
// ユーザーIDをセッションに格納してリダイレクト
return redirect("/home")
.addingToSession(request, "user_id", "admin_user_001");
}
}
この方法は、ブラウザがクッキーを自動管理してくれるため、開発者が複雑なトークン管理ロジックを書く必要がないというメリットがあります。
4. セッションから値を取得して表示する方法
次に、保存したセッションデータを取得する方法を確認します。
リクエストから session() を呼び出し、キーを指定して値を取り出します。
値が存在しない場合に備えて、JavaのOptionalを活用するのがベストプラクティスです。
package controllers;
import play.mvc.*;
import java.util.Optional;
public class HomeController extends Controller {
public Result index(Http.Request request) {
// セッションからユーザー名を取得
Optional<String> user = request.session().get("user_id");
return user.map(u -> ok("ログイン中: " + u))
.orElseGet(() -> unauthorized("ログインしていません"));
}
}
実行結果のイメージは以下の通りです。
ログイン中: admin_user_001
5. JWTを使ったAPI認証の実装イメージ
JWTを自前で発行する場合、ライブラリを使用してトークンを生成し、JSONとしてクライアントに返却します。 クッキーではなくレスポンスボディに載せることで、クライアント側(スマホアプリなど)で自由に保存場所を選べるようになります。
package controllers;
import play.mvc.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import play.libs.Json;
public class ApiAuthController extends Controller {
public Result apiLogin() {
// 本来はここでJWTライブラリを使いトークンを生成します
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
ObjectNode result = Json.newObject();
result.put("access_token", token);
// JSON形式でトークンを返却
return ok(result);
}
}
クライアントはこのトークンを受け取り、次回以降のリクエストで Authorization: Bearer [トークン] というヘッダーを付けて送信します。
6. セッションとJWTのメリットとデメリット比較
どちらを採用すべきか判断するために、主要な違いを整理しましょう。 セッション(クッキー方式)は、ブラウザの標準機能であるCSRF対策やHttpOnly属性を利用できるため、Webサイトとしてのセキュリティを確保しやすいのが利点です。 一方で、スマホアプリなど「クッキー」という概念が薄い環境では扱いが難しくなります。
JWT(トークン方式)は、ドメインをまたいだ認証や、マイクロサービス間での情報伝達に優れています。 しかし、一度発行したトークンをサーバー側で無効化するのが難しい(ブラックリスト管理が必要)という運用上の課題もあります。 Play Frameworkのセッションは、実は「中身が署名されたクッキー」であるため、概念としては「ブラウザ専用のJWT管理システム」に近い存在と言えます。
7. application.confでのセキュリティ設定
セッションを使うにせよ、JWTをクッキーで管理するにせよ、設定ファイルでの調整は不可欠です。
Play Frameworkでは application.conf で詳細な挙動を制御できます。
# クッキーのセキュリティ設定
play.http.session.httpOnly = true
play.http.session.secure = true
play.http.session.sameSite = "lax"
# セッションの有効期限設定(例:2時間)
play.http.session.maxAge = 2h
これらの設定を正しく行うことで、セッションハイジャックなどの攻撃リスクを大幅に下げることができます。
初心者のうちは、まず httpOnly が true になっていることを必ず確認しましょう。
8. ログアウト処理における実装の違い
ログアウトの挙動も、両者で異なります。 セッションの場合は、サーバーが「クッキーを消去して」という命令をブラウザに送るだけで完了します。
package controllers;
import play.mvc.*;
public class LogoutController extends Controller {
public Result logout() {
// セッションを完全に破棄
return redirect("/login").withNewSession();
}
}
JWTの場合は、クライアント側で保存しているトークンを削除するだけで済みますが、より厳密に管理したい場合は、サーバー側に「使用済みトークンの一覧」を保持する仕組みが必要になります。
初心者のうちは、まずはPlay Frameworkの標準セッション機能を使った withNewSession によるログアウトをマスターしましょう。
9. 最適な認証方式を選ぶための判断基準
最後に、使い分けの基準をまとめます。 あなたが作っているのが「一般的なWebブラウザで動く管理画面やブログ」なら、迷わずPlay Frameworkの標準セッション機能を使ってください。 これが最も安全で、フレームワークの恩恵を最大限に受けられる方法です。
もし「スマホアプリ向けのバックエンド」や「複数のサービスで共通のログイン機能」を作っているなら、JWTの導入を検討すべきです。 それぞれの特性を理解し、プロジェクトの要件に合わせて最適な道具を選べるようになることが、脱・初心者への近道となります。 Javaでの実装は非常にシンプルなので、まずは実際にコードを動かして、ブラウザの中でクッキーがどう変化するかを観察してみてください。