3秒でわかる
同じ利用者からの複数のリクエストをまたいでデータを保持する範囲。ログイン状態やカートの中身のように、画面遷移しても消えては困る値を置きます。
もう少し詳しく
どういうものか
セッションスコープは、Java の Web アプリでデータを置く場所の広さを表す区分のひとつで、同じ利用者からの複数のリクエストをまたいでデータが生き続ける範囲を指します。実体は HttpSession で、サーバー側にデータを保管し、ブラウザには識別子 (JSESSIONID) だけを Cookie で渡す仕組みです。
保持されるのは、ブラウザを閉じるか、設定したタイムアウト時間が経過するまでです。既定値はサーブレットコンテナ側で決まっており、Tomcat では 30 分が一般的です。
なぜ必要か
HTTP はリクエストごとに完結し、前のリクエストのことを覚えていません。何もしなければ、ログイン画面で認証した次の瞬間、商品一覧を開いた時点で「誰なのか」が分からなくなります。
セッションスコープはこの断絶を埋めるための場所です。ログイン中のユーザー情報、カートの中身、複数画面にまたがる申込フォームの途中経過は、リクエストをまたいで残す必要があるためここに置きます。逆に、1 回の表示にしか使わない検索結果をここに置くと、利用者が増えたときにサーバーのメモリを圧迫します。
具体例
サーブレットでログイン情報をセッションに入れ、別のリクエストで取り出します。
// ログイン処理 (LoginServlet)
User user = userService.authenticate(email, password);
if (user != null) {
HttpSession session = request.getSession();
session.setAttribute("loginUser", user);
session.setMaxInactiveInterval(30 * 60); // 30 分で失効
response.sendRedirect("/items");
}
// 別のリクエスト (ItemServlet)
HttpSession session = request.getSession(false); // 無ければ作らない
User loginUser = (session == null) ? null : (User) session.getAttribute("loginUser");
if (loginUser == null) {
response.sendRedirect("/login");
return;
}似た用語との違い
| スコープ | 生存範囲 | 置くもの |
|---|---|---|
| リクエストスコープ | 1 リクエストの間だけ | 画面に渡す検索結果 |
| セッションスコープ | 同じ利用者の一連の操作 | ログイン情報、カート |
| アプリケーションスコープ | アプリ全体で共有 | 設定値、マスタ一覧 |
つまずきやすいところ
getSession() と getSession(false) の違いを知らずに使う。引数なしは無ければ新規作成するため、ログイン判定に使うと必ず新しい空のセッションが作られ、未ログインを検出できませんsession.invalidate() してから新しいセッションを作らず、セッション固定攻撃の余地を残す。ログイン直後にセッションを作り直すのが定石ですinvalidate() でセッションごと破棄します覚え方
リクエストは 1 画面かぎり、セッションは 1 人ぶん、アプリケーションは全員ぶん。この 3 段の広さで使い分けます。