3秒でわかる
Javaのサーブレットで利用者ごとの情報をサーバー側に保持する仕組み。IDだけをCookieで渡すため、ログイン状態を改ざんされずに維持できます。
30秒図解
もう少し詳しく
どういうものか
HttpSession は、Java のサーブレット仕様で用意されている、利用者ごとのデータをサーバー側に置いておくための仕組みです。最初のアクセス時にセッションIDが発行され、JSESSIONID という名前の Cookie でブラウザへ渡されます。以降のリクエストにはその Cookie が付いてくるので、サーバーは「これはさっきの人だ」と判別し、保存しておいた値を取り出せます。
なぜ必要か
HTTP は 1 回のやり取りごとに関係が切れる仕様で、前のリクエストのことを覚えていません。この前提のままだと、ログイン後にページを移動した瞬間にログイン状態が消えます。セッションはこの穴を埋めるもので、ID だけをブラウザに持たせ、中身はサーバーに置きます。中身が手元に無いので、利用者が値を書き換えて権限を上げるといった改ざんができません。
具体例
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws <a href="/glossary/ioexception" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">IOException</a> {
User user = auth(req.getParameter("id"), req.getParameter("pw"));
if (user == null) { res.sendError(401); return; }
req.getSession().invalidate(); // 固定化攻撃を防ぐため作り直す
HttpSession session = req.getSession(true);
<a href="/glossary/session-setattribute" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">session.setAttribute</a>("userId", user.getId());
session.setMaxInactiveInterval(1800); // 30分で失効
res.sendRedirect("/mypage");
}
}取り出す側は session.getAttribute("userId") で読み、Object から元の型へ戻します。
つまずきやすいところ
getSession() は引数なしだと、存在しないとき新しいセッションを作ります。存在確認のつもりで呼ぶと毎回新規作成され、無駄なセッションが積み上がります。確認だけなら getSession(false) を使い、null かどうかを見ます。もうひとつは、ログイン成功時に古いセッションを作り直さない実装で、攻撃者が事前に用意したIDをそのまま使われる危険があります。サーバーを複数台に増やしたときは、置き場がメモリのままだと台をまたいだ瞬間にログアウトするため、共有ストアへ移すか、振り分けを固定する設定が要ります。
似た用語との違い
| 用語 | 保存場所 |
|---|---|
| HttpSession | サーバー側。ブラウザにはIDだけ |
| Cookie | ブラウザ側。中身が利用者から見える |
| JWT | ブラウザ側。署名付きでサーバーは保持しない |