ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
セッションとは
HTTP はリクエストごとに独立しているため、そのままでは「誰からのアクセスか」が分かりません。サーバーがセッション ID を Cookie(JSESSIONID)で渡し、その ID に紐づく保管場所を用意する仕組みがセッションです。
1 回目のアクセス ブラウザ → サーバー
サーバー: セッションを作り Set-Cookie: JSESSIONID=ABC123
2 回目以降 ブラウザ: Cookie: JSESSIONID=ABC123
サーバー: ABC123 の保管場所を取り出す
基本操作
@WebServlet("/mypage")
public class MyPageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
HttpSession session = request.getSession(); // 無ければ作る
// HttpSession s2 = request.getSession(false); // 無ければ null
// 保存
session.setAttribute("userId", 42);
session.setAttribute("user", new User(42, "田中"));
// 取得(Object で返るのでキャストする)
Integer userId = (Integer) session.getAttribute("userId");
User user = (User) session.getAttribute("user");
// 削除
session.removeAttribute("userId");
// 情報
System.out.println(session.getId());
System.out.println(session.isNew());
System.out.println(session.getCreationTime());
System.out.println(session.getLastAccessedTime());
}
}
getSession(false) は「あれば返す、無ければ null」です。ログイン判定のように「作りたくない」場面ではこちらを使ってください。引数なしで呼ぶと、未ログインの訪問者にもセッションが作られ、メモリを消費します。
取り出しは null とキャストに注意
HttpSession session = request.getSession(false);
if (session == null) {
response.sendRedirect("/login");
return;
}
Object raw = session.getAttribute("userId");
if (raw == null) {
response.sendRedirect("/login");
return;
}
// 型が違うと ClassCastException
if (!(raw instanceof Integer userId)) {
session.invalidate();
response.sendRedirect("/login");
return;
}
// ヘルパーを用意しておくと安全
private static <T> Optional<T> attr(HttpSession s, String key, Class<T> type) {
if (s == null) return Optional.empty();
Object v = s.getAttribute(key);
return type.isInstance(v) ? Optional.of(type.cast(v)) : Optional.empty();
}
ログイン処理
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
User user = authenticate(request.getParameter("id"),
request.getParameter("password"));
if (user == null) {
request.setAttribute("error", "IDまたはパスワードが違います");
return;
}
// 1. セッション ID を作り直す(セッション固定化攻撃への対策)
request.changeSessionId();
// 2. 必要な情報だけ保存する
HttpSession session = request.getSession();
session.setAttribute("userId", user.getId());
session.setMaxInactiveInterval(30 * 60); // 30 分無操作で失効
response.sendRedirect("/mypage");
}
changeSessionId() を呼ばないと、攻撃者があらかじめ用意した ID のままログインが成立します。その ID を知っている攻撃者は、そのままログイン済みの状態を使えてしまいます(セッション固定化)。Servlet 3.1 以降で使えます。
ログアウト
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate(); // セッションを破棄する
}
// session.getAttribute("x"); // IllegalStateException: 破棄後は触れない
// Cookie も消したいとき
Cookie cookie = new Cookie("JSESSIONID", "");
cookie.setMaxAge(0);
cookie.setPath(request.getContextPath() + "/");
response.addCookie(cookie);
response.sendRedirect("/login");
有効期限
session.setMaxInactiveInterval(1800); // 秒。この時間アクセスが無ければ失効
session.setMaxInactiveInterval(-1); // 無期限(推奨しない)
System.out.println(session.getMaxInactiveInterval());
<!-- web.xml で既定値を決める(分単位) -->
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
<same-site>Lax</same-site>
</cookie-config>
</session-config>
| Cookie 属性 | 意味 | 推奨 |
|---|---|---|
HttpOnly | JavaScript から読めなくする | 必ず有効(XSS でセッションを盗まれない) |
Secure | HTTPS のときだけ送る | 本番では有効 |
SameSite | 他サイト由来のリクエストで送るか | Lax。決済系は Strict |
Spring MVC での書き方
@Controller
public class MyPageController {
// HttpSession をそのまま受け取れる
@GetMapping("/mypage")
public String mypage(HttpSession session, Model model) {
Object userId = session.getAttribute("userId");
if (userId == null) return "redirect:/login";
model.addAttribute("userId", userId);
return "mypage";
}
}
// セッションに載せるモデル属性を宣言する
@Controller
@SessionAttributes("cart")
public class CartController {
@ModelAttribute("cart")
public Cart cart() { return new Cart(); }
@PostMapping("/cart/clear")
public String clear(SessionStatus status) {
status.setComplete(); // @SessionAttributes の分だけ破棄する
return "redirect:/cart";
}
}
実際の認証には Spring Security を使うのが標準です。セッション固定化対策やタイムアウト、同時ログイン数の制御が設定だけで有効になります。
何を入れて何を入れないか
| 入れてよい | 入れない |
|---|---|
| ユーザー ID・権限などの小さな値 | パスワード・カード番号 |
| 画面の入力途中の状態(ウィザード) | 検索結果の全件(数 MB になる) |
| CSRF トークン | DB から取れる情報の丸ごとコピー |
| 直列化できるオブジェクト | Connection や InputStream などの資源 |
セッションは利用者ごとにサーバーのメモリを消費します。同時 1,000 人で 1 人 1MB を持てば 1GB です。大きなデータは ID だけ保存し、必要なときに取り直してください。
複数台構成での注意
// Spring Session + Redis を使うと、サーバーをまたいで共有できる
// build.gradle:
// implementation 'org.springframework.session:spring-session-data-redis'
// application.properties:
// spring.session.store-type=redis
// spring.session.timeout=30m
既定のセッションはそのサーバーのメモリ上にあります。ロードバランサで振り分けると、別のサーバーに届いた時点でログイン状態が消えます。対処は次のいずれかです。
- 外部ストアに置く(Redis / DB)— 台数を増やしても影響がなく、再起動でも消えない
- 同じ利用者を同じサーバーへ送る(スティッキーセッション)— 簡単だが偏りやすく、再起動で失う
- セッションを使わず JWT などトークンで持つ — 失効の扱いが別途必要になる
セッションに入れるクラスは直列化できるようにする
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private transient Connection conn; // 保存しないものは transient
}
Tomcat は再起動時にセッションをファイルへ書き出します(セッションの永続化)。Serializable でないオブジェクトが入っていると NotSerializableException が出て、セッションが失われます。
関連
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- 【django】ログイン 認証機能 2026-09-08 03:22:09
- MySQL ERROR 1063 Incorrect column specifier for column|原因と直し方 2026-09-08 03:11:09
- 【PHPエラー】Object of class stdClass could not be converted to string 2026-09-07 07:46:04
- Julia Genie ローカル開発サーバ起動完全ガイド 2026-09-07 07:46:04
- Wi-Fi とは|規格と世代(Wi-Fi 4〜7)・周波数帯・CSMA/CA・WPA3 NEW 2026-09-07 07:45:13
- set コマンドでシェルオプションと位置パラメータを操作 | bash 2026-09-07 07:45:13
- JPEG(.jpg/.jpeg)画像形式の完全ガイド — 仕様・マジックナンバー・他形式との比較・EXIF 2026-09-07 07:45:13
- UE5 Get Overlapping Actorsで特定クラスだけ処理|Class Filter・Cast To 2026-09-07 07:45:13
- Linuxで特定拡張子のファイルを再帰削除|find -deleteの安全手順 2026-09-07 07:45:13
- Django CBVでテンプレートに値を渡す|get_context_data・extra_context 2026-09-07 07:45:13
- Linuxで複数ファイルの文字列を一括置換|find・sed・xargsの安全手順 2026-09-07 07:45:13
- Laravelルートグループ|prefix・middleware・nameで一括管理 2026-09-07 07:45:13
- Linux whichコマンドの使い方|絶対パス取得とtype・command -vの違い 2026-09-07 07:45:13
- Linux catコマンドの使い方|行番号表示・複数ファイル連結 2026-09-07 07:45:13
- unable to execute 'gcc': No such file or directory 2026-09-07 07:45:13
コメントを削除してもよろしいでしょうか?