一覧へ

CookieとSessionでログインを理解する

Cookie、Session、ログインの動作原理を実験室の例えで説明します。HTTPステートレスの意味と認証メカニズムの基礎を学びます。

入門
|
45
|
検証済み (2026-06)
Cookieセッション認証ログインHTTPパーソナライズ
進捗0/19 (0%)

CookieとSessionでログインを理解する

これまで作った試料管理APIサーバーには1つ大きな問題があります。誰でも試料を登録し、修正し、削除できるということです。実験室で機器室の入退室にカードキーが必要なように、Webサービスにも「この人が誰か確認する手続き」— **認証(Authentication)**が必要です。

ログインはどう動くのでしょうか?この質問に答えるにはまず、Webの根本的な特性を理解する必要があります。

HTTPは記憶できない

Webの通信プロトコルであるHTTPは**ステートレス(stateless)**です。サーバーはリクエストを処理しレスポンスを送った瞬間、そのユーザーが誰だったかを即座に忘れてしまいます。

例えると — 受付デスクの担当者が5秒ごとに記憶がリセットされる状態です。「試料S001の結果を教えてください」→ 結果を伝える →(リセット)→「さっき試料S001について聞いたんですが」→「どちら様ですか?」

リクエストのたびに「私は田中研究員です」と再度名乗らなければなりません。この不便さを解消するために1994年にCookieが発明されました。

Cookie:ブラウザに貼る名札

Cookieはサーバーがブラウザに渡す小さなテキストデータです。ブラウザはこのデータを保存しておき、同じサーバーへのリクエスト時に自動で一緒に送ります。

text
[1] ログインリクエスト
  ブラウザ → サーバー: "ID tanaka、パスワード 1234"
  サーバー → ブラウザ: "確認完了!このCookieを持ち歩いて"
                   Set-Cookie: user=tanaka

[2] 以降のリクエスト(自動)
  ブラウザ → サーバー: "試料リストをください" + Cookie: user=tanaka
  サーバー: "あ、田中研究員だね。試料リストを送るよ"

[3] さらに別のリクエスト(自動)
  ブラウザ → サーバー: "S001の詳細" + Cookie: user=tanaka
  サーバー: "田中研究員のリクエストだね。S001情報を送るよ"

実験室の入退室カードと同じです。一度発行されれば毎回身分を証明する必要がなく、カードを見せるだけで済みます。

ExpressでCookieを扱う

javascript
const express = require("express");
const app = express();

app.get("/login", function(req, res) {
  res.setHeader("Set-Cookie", "user=tanaka; Path=/");
  res.send("ログイン完了");
});

app.get("/whoami", function(req, res) {
  const cookies = req.headers.cookie;
  res.send("現在のCookie: " + cookies);
});

app.listen(3000);

/loginにアクセスするとサーバーがSet-CookieヘッダーでCookieを送り、その後/whoamiにアクセスするとブラウザが自動でCookieを送るのが確認できます。

Cookieの限界:なぜSessionが必要なのか

Cookieだけで認証すると深刻な問題があります。Cookieはブラウザに保存されます。ブラウザの開発者ツールを開けば誰でもCookieの内容を見て、変更することもできます。

もしCookie: user=tanakaのようにユーザー名を直接Cookieに入れると、誰かがCookie: user=adminに書き換えて管理者になりすますことができます。

実験室の例え — 入退室カードに「名前:田中研究」と書いてあって、誰でも修正テープで名前を変えられるなら入退室管理は無意味です。

**Session(セッション)**がこの問題を解決します。

Session:サーバーが管理する入退室記録

Sessionの核心アイデア — 機密情報はサーバーに保存し、ブラウザには識別番号だけを渡す。

text
[1] ログイン成功
  サーバー内部: { session_abc123: { user: "tanaka", role: "researcher" } }
  サーバー → ブラウザ: Set-Cookie: session_id=abc123

[2] 以降のリクエスト
  ブラウザ → サーバー: Cookie: session_id=abc123
  サーバー: abc123セッションを検索 → { user: "tanaka", role: "researcher" }
       → "田中研究員だね"

ブラウザが持っているのはabc123という意味のない番号だけです。この番号を変えてみても、サーバーに登録されたセッションでなければ無効です。

実験室の例え — 入退室カードにバーコードだけが印刷されていて、実際の身元情報は警備室のコンピュータにあるのと同じです。カードをコピーしてもバーコードがデータベースになければドアは開きません。

CookieのみSession(Cookie + サーバー側ストレージ)
データの場所ブラウザサーバー
セキュリティユーザーが変更可能(危険)サーバーのみ変更可能(安全)
容量4KB制限サーバーメモリ/DBベース(制限なし)
例え名前が書いてある入退室カードバーコードだけのカード + 警備室DB

Cookieのセキュリティオプション

Cookie自体にもセキュリティ設定ができます:

text
Set-Cookie: session_id=abc123; HttpOnly; Secure; Path=/; Max-Age=3600
オプション意味なぜ必要か
HttpOnlyJavaScriptからCookieにアクセス不可悪意あるスクリプト(XSS)によるCookie窃取を防止
SecureHTTPSでのみCookieを送信ネットワーク盗聴によるCookie漏洩を防止
Max-Age=36003600秒(1時間)後に自動削除古いログイン状態が無期限に維持されるのを防止
Path=/このパス以下のリクエストでのみCookieを送信不要なCookie送信範囲を制限

Max-AgeがないCookieはブラウザを閉じると消えます — これを**セッションCookie(Session Cookie)と言います。Max-AgeがあるCookieはブラウザを閉じても残ります — これを永続Cookie(Permanent Cookie)**と言います。

現代の認証:トークンベース

現代のWebサービスではセッションIDの代わりに**JWT(JSON Web Token)**というトークンを使うことが多いです。BioPlaygroundが使うSupabaseもJWTベースの認証です。

原理はセッションと似ていますが、違いがあります:

セッション方式トークン(JWT)方式
サーバー状態セッションストレージが必要サーバーに保存不要
検証セッションDB照会トークン自体の署名検証
スケーラビリティサーバーが複数台ならセッション共有が必要サーバー間の共有不要

深い実装はこの段階では扱いません。重要なのはメカニズムを理解することです:

  1. ユーザーがID/パスワードを送る
  2. サーバーが確認し、識別子(セッションIDまたはトークン)を発行
  3. ブラウザが以降のリクエストに識別子を自動添付
  4. サーバーが識別子で「この人が誰か」を確認

すべてのログインシステムはこの4ステップの変形です。

やってみよう(Faded Example)

空欄を埋めてCookieベース認証のフローを完成させてください。

穴埋め問題javascript
// 1. ログイン:サーバーがCookieを発行
app.post("/login", function(req, res) {
res.setHeader("", "session_id=xyz789; HttpOnly; Path=/");
res.json({ message: "ログイン成功" });
});
// 2. 保護されたAPI:Cookieでユーザー確認
app.get("/my-samples", function(req, res) {
const cookies = req.headers.;
if (!cookies || !cookies.includes("session_id")) {
return res.status().json({ error: "ログインが必要です" });
}
res.json({ samples: ["S001", "S002"] });
});

よくあるエラーと解決法

Q: Cookieが送信されません(req.headers.cookieがundefined)

ブラウザの開発者ツール(F12)→ Application → Cookiesで、該当ドメインのCookieが存在するか確認してください。Secureオプションが有効な場合、HTTP(localhost)では送信されません。開発中はSecureを外すかHTTPSを使ってください。

Q: Set-Cookieヘッダーを送ったのにブラウザがCookieを保存しません

フロントエンドとバックエンドのドメイン(またはポート)が異なるとCORSポリシーによりCookieがブロックされます。fetch呼び出し時にcredentials: 'include'オプションを追加し、サーバーでAccess-Control-Allow-Credentials: trueヘッダーを設定してください。

Q: SessionとCookieの違いを一言で説明してください

Cookieは「ブラウザに保存されるデータ」、Sessionは「サーバーに保存されたデータをCookieのIDで見つけるシステム」です。SessionはCookieの上に成り立つ概念です。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...