Java | Web 基礎・HTTP・REST:HTTP 詳細 - セッション

Java Java
スポンサーリンク

セッションを一言でいうと

セッションは
「同じユーザーからの一連のリクエストを“ひとまとまり”として扱うためのサーバー側の仕組み」
です。

HTTP は本来「1 回 1 回がバラバラで、前後のつながりを覚えない」プロトコルですが、
セッションを使うことで、
「このリクエストは、さっきログインしたあのユーザーからだ」と認識できるようになります。

ログイン状態の維持、カートの中身の保持、ウィザード形式の入力など、
“継続している状態”が必要な場面で必ず出てくる概念です。


HTTP が「覚えてくれない」からセッションが必要になる

ステートレスな HTTP の限界

HTTP はステートレス(無状態)です。
1 回目のリクエストと 2 回目のリクエストの間に、
「これは同じ人だよ」という情報は、プロトコル的には一切ありません。

だから、そのままだと

ログインしても、次のリクエストで誰だか分からない
カートに商品を入れても、次の画面で忘れられる
「前の画面で入力した内容」を引き継げない

という状態になります。

ここで登場するのが「セッション」です。

セッションの直感イメージ

セッションは、
「サーバー側に置いておく“ユーザーごとのメモ帳”
だと思ってください。

「このユーザーはログイン済み」
「このユーザーのカートには商品 A と B が入っている」

といった情報を、
サーバー側のメモ帳(セッションストア)に保存しておき、
次のリクエストでもそれを参照できるようにします。


セッションと Cookie の関係

セッション ID という“鍵”を Cookie に入れる

サーバー側に「ユーザーごとのメモ帳(セッション)」を作ったとして、
問題は「どのメモ帳がどのユーザーのものか」をどうやって見分けるか、です。

そこで使うのが「セッション ID」です。

流れはこうなります。

サーバーがランダムなセッション ID(例:abc123)を発行する
サーバー側に「abc123 → ユーザーID=1、ログイン済み」などの情報を保存する
レスポンスで Set-Cookie: JSESSIONID=abc123 を返す
ブラウザは JSESSIONID=abc123 を保存し、次回以降のリクエストで Cookie: JSESSIONID=abc123 を送る
サーバーは abc123 を見て、対応するセッション情報を取り出す

つまり、

セッションの中身(ログイン状態など)はサーバー側に置く
そのセッションを指す“鍵(ID)”だけを Cookie に入れてブラウザに持たせる

という分担になっています。

なぜ中身を Cookie に入れないのか

Cookie はクライアント側で見えるし、書き換えもできます。
もし「ユーザーID=1」などをそのまま Cookie に入れて信用してしまうと、
書き換えられて不正アクセスされる危険があります。

だから、

Cookie には「意味のないランダムな ID(セッション ID)」だけ
本当の情報(ユーザー ID、権限、カートの中身など)はサーバー側のセッションに保存

という設計が安全です。


Java(Spring)におけるセッションのイメージ

JSESSIONID と HttpSession

Java(サーブレット/Spring)では、
セッションは HttpSession というオブジェクトで扱います。

ブラウザからのリクエストに対して、
サーバーは自動的にセッションを作り、
JSESSIONID という Cookie でセッション ID をやり取りします。

コードのイメージはこんな感じです。

@GetMapping("/login-success")
public String loginSuccess(HttpServletRequest request) {
    HttpSession session = request.getSession(); // なければ新規作成
    session.setAttribute("userId", 1L);
    session.setAttribute("userName", "Alice");
    return "redirect:/mypage";
}
Java

次のリクエストでは、同じセッションを取り出せます。

@GetMapping("/mypage")
public String mypage(HttpServletRequest request, Model model) {
    HttpSession session = request.getSession(false); // なければ null
    if (session == null) {
        return "redirect:/login";
    }
    Long userId = (Long) session.getAttribute("userId");
    String userName = (String) session.getAttribute("userName");
    if (userId == null) {
        return "redirect:/login";
    }
    model.addAttribute("userName", userName);
    return "mypage";
}
Java

ここで重要なのは、
「セッションはサーバー側のメモ帳であり、Cookie はそのメモ帳の鍵を持っているだけ」
という構造です。


セッションがよく使われる場面

ログイン状態の維持

典型的な例はログインです。

ログイン成功時に

セッションに userIdroles(権限)を保存する
以降のリクエストでセッションを見て「この人は誰か」「何ができるか」を判断する

という流れになります。

Spring Security を使うと、
このあたりをフレームワークがかなり自動化してくれますが、
裏側では結局「セッション+Cookie」でユーザーを識別しています。

カートや一時的な入力内容の保持

EC サイトのカート
複数画面にまたがる入力フォーム(ステップ 1 → 2 → 3)

なども、セッションに一時的に保存しておくことが多いです。

ただし、
セッションに入れすぎるとメモリを圧迫するので、
「何でもかんでもセッションに突っ込む」のは NG です。


セッションで気をつけるべきポイント(重要)

1. セッションはサーバーのリソースを消費する

セッションはサーバー側のメモリやストレージを使います。
ユーザーが増えるほど、セッションも増えます。

だから、

不要になったセッションはタイムアウトで破棄する
巨大なデータをセッションに入れない

といった設計が必要です。

2. セッション固定攻撃などのセキュリティリスク

セッション ID が盗まれたり、
攻撃者に固定されたりすると、
「なりすまし」が起きます。

ログイン前後でセッション ID を再発行する
セッション ID を URL に埋め込まない(Cookie でやり取りする)
SecureHttpOnly を付ける

などの対策が重要です。

3. REST 的な世界では「できるだけステートレス」が好まれる

REST API の設計では、
「サーバー側にセッション状態を持たない(ステートレス)」
ことが理想とされます。

その代わりに、
各リクエストにトークン(JWT など)を付けて認証する、
というスタイルがよく使われます。

とはいえ、
ブラウザベースの Web アプリでは、
今でもセッション+Cookie は現役バリバリです。


初心者向けまとめ:セッションを自分の言葉で説明するなら

あなたの言葉で整理すると、こうなります。

セッションは、
「ステートレスな HTTP の上に、“同じユーザーからの一連のリクエスト”をひとまとまりとして扱うための、サーバー側のメモ帳」。

サーバーはランダムなセッション ID を発行し、
その ID とユーザー情報・ログイン状態などをサーバー側に保存する。
ブラウザには Cookie(JSESSIONID など)でその ID だけを渡し、
次回以降のリクエストでその ID を送り返してもらうことで、
「このリクエストは誰のものか」を認識できる。

もしよければ、
「ログイン成功 → マイページ表示」までの流れを、
セッションと Cookie の視点で自分の言葉で図解してみて。
それを説明できるようになったとき、セッションはもう“フレームワークの黒魔術”じゃなくて、あなたが理解してコントロールできる仕組みになっているはず。

タイトルとURLをコピーしました