3秒でわかる
サーバー側が利用者ごとの状態を覚えておく仕組み。毎回接続が切れるHTTPでもログイン状態を続けさせるために、識別子をブラウザへ預けて紐づけます。
30秒図解
もう少し詳しく
どういうものか
セッションは、サーバーが利用者ごとの一時的な状態を覚えておく仕組みです。ログインが成功した時点でサーバーがセッションを作り、そこに利用者 ID などを記録し、識別子であるセッション ID だけを Cookie としてブラウザに返します。以降のリクエストにはその Cookie が自動で付くので、サーバーは ID を手掛かりに「これは誰からのリクエストか」を判断できます。
なぜ必要か
HTTP は一回のやり取りが終わると相手を忘れる設計です。この性質のままだと、ページを移動するたびにログインし直すことになります。かといって利用者 ID をそのまま Cookie に入れると、値を書き換えるだけで他人になりすませてしまいます。推測できないセッション ID だけを渡し、中身はサーバーが持つことで、この問題を避けています。
具体例
import express from "express";
import session from "express-session";
const app = express();
<a href="/glossary/app-use" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">app.use</a>(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: { httpOnly: true, secure: true, sameSite: "lax", maxAge: 1800000 },
}));
app.post("/login", (req, res) => {
// 認証が通ったとして
req.session.regenerate(() => {
req.session.userId = 42;
res.redirect("/mypage");
});
});
app.post("/logout", (req, res) => {
req.session.destroy(() => res.redirect("/"));
});httpOnly は JavaScript から Cookie を読めなくする指定、secure は HTTPS のときだけ送る指定です。
似た用語との違い
| 語 | 状態の置き場所 | 取り消し |
|---|---|---|
| セッション | サーバー側 | サーバーで消せば即時 |
| Cookie | ブラウザ側 | 運ぶ入れ物そのもの |
| JWT | トークン内部(署名付き) | 期限切れまで有効になりがち |
つまずきやすいところ
ログイン成功時にセッション ID を作り直さないと、攻撃者があらかじめ用意した ID を被害者に使わせるセッションフィクセーションが成立します。上の例で regenerate を呼んでいるのはこのためです。もう一つ多いのが、サーバーを複数台に増やしたとたんに「たまにログアウトする」という症状です。既定のセッション保存先がプロセスのメモリなので、別の台に振り分けられると相手を知らないまま扱われます。Redis など共有の保存先に移すか、振り分けを固定して解決します。