3秒でわかる
Java Servlet でセッションに値を保存するメソッド。ログイン状態やカートなど、リクエストをまたいで覚えたい情報をサーバー側に置くために使います。
30秒図解
もう少し詳しく
どういうものか
session.setAttribute(名前, 値) は、HttpSession にキーと値の組でオブジェクトを預けるメソッドです。取り出すのは getAttribute、捨てるのは removeAttribute。セッションはブラウザごとに一つ作られ、JSESSIONID という Cookie でどのセッションかを見分けています。
なぜ必要か
HTTP は一回の往復ごとに関係が切れるステートレスな仕組みです。サーバーは次のリクエストが来たとき、それがさっきログインした人なのか初対面なのかを、そのままでは判別できません。
ログイン済みかどうか、カートに何を入れたか、複数ページにまたがる申込みフォームの入力途中。こうした「前の画面から引き継ぎたい情報」をサーバー側に置いておく箱がセッションです。Cookie に直接持たせるとブラウザ側で書き換えられますが、セッションは値がサーバーにあり、クライアントが持つのは ID だけなので改ざんされません。
具体例
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException {
User user = userService.authenticate(
req.getParameter("email"), req.getParameter("password"));
if (user == null) {
res.sendRedirect("/login?error=1");
return;
}
// セッション固定攻撃を避けるため ID を作り直してから保存する
req.changeSessionId();
HttpSession session = req.getSession();
session.setAttribute("loginUser", user);
session.setMaxInactiveInterval(30 * 60); // 30分で失効
res.sendRedirect("/mypage");
}
}
// 別のサーブレットで取り出す
User user = (User) req.getSession().getAttribute("loginUser");
if (user == null) {
res.sendRedirect("/login");
}つまずきやすいところ
getAttribute の戻り値は Object なので、必ずキャストが要ります。ここで型を間違えると ClassCastException になります。
キー名を打ち間違えても例外は出ず、静かに null が返ってくるだけです。"loginUser" と "loginuser" の取り違えは自分では気づきにくいので、キーは定数にまとめておくと事故が減ります。
ログイン成功時に changeSessionId を呼ばないと、攻撃者が用意した ID をそのまま使い続けられるセッション固定攻撃が成立します。サーバーを複数台に増やす場合は、直列化できるオブジェクトでないと共有できない点にも注意します。
似た用語との違い
| 保存先 | 生きている範囲 |
|---|---|
request.setAttribute | その 1 リクエストの中だけ。転送先の JSP まで |
session.setAttribute | 同じブラウザからの一連のアクセス。既定は 30 分 |
ServletContext.setAttribute | アプリ全体。全利用者で共有される |
| Cookie | ブラウザ側に保存。利用者が中身を見られる |
覚え方
リクエストは一往復ぶん、セッションは一人ぶん、コンテキストは全員ぶん。範囲の広さで三段階に並べて覚えます。