「ログインしたのに、ページを移動したら情報が消えてしまった…」「Cookieとセッションって何が違うの?」——Flaskを使い始めたばかりのころ、こんな疑問を持ったことはありませんか?
WebアプリではHTTPというプロトコルを使って通信しますが、HTTPはステートレス(状態を持たない)という性質があります。つまり、リクエストのたびに「誰が送ってきたのか」をサーバーは忘れてしまいます。ログイン状態やカートの中身を覚えておくために必要なのが、CookieとSession(セッション)の仕組みです。
この記事では、Cookie・クライアントサイドセッション・サーバーサイドセッションの3つをわかりやすいたとえ話とFlaskの実装コードを交えて解説します。「なんとなく動かせているけど、違いがよくわからない」という方はぜひ最後まで読んでみてください!
🍪 Cookieとは何か?

仕組みと特徴
Cookieとは、サーバーがブラウザに保存させる小さなデータのことです。サーバーがHTTPレスポンスヘッダーに Set-Cookie を含めてブラウザに送ると、ブラウザはそのデータを保存し、次回以降のリクエスト時に自動的にサーバーへ送り返します。
たとえ話でいうと、「鍵付きロッカーに入れた荷物」のイメージです。サーバーが荷物(データ)を用意してロッカーに入れ、あなた(ブラウザ)はその荷物を読んだり、自分で中身を書き換えたりすることもできます。
- データはブラウザ(クライアント側)に保存される
- 文字列として中身が見える・書き換えられる(暗号化しない場合)
- 有効期限(expires)を設定できる
- ドメイン・パスを指定してスコープを絞れる
具体的なユースケース
- 「次回もログイン状態を保持する」チェックボックス
- ECサイトの言語設定・表示設定の保存
- アクセス解析用のトラッキングID
- セッションIDの受け渡し(後述)
FlaskでCookieを操作する
from flask import Flask, request, make_response
app = Flask(__name__)
# Cookieをセットするエンドポイント
@app.route('/set_cookie')
def set_cookie():
resp = make_response('Cookieをセットしました!')
# max_age=秒数で有効期限を設定
resp.set_cookie('username', 'taro', max_age=60*60*24) # 1日間
return resp
# Cookieを読み取るエンドポイント
@app.route('/get_cookie')
def get_cookie():
username = request.cookies.get('username', 'ゲスト')
return f'こんにちは、{username}さん!'
# Cookieを削除するエンドポイント
@app.route('/delete_cookie')
def delete_cookie():
resp = make_response('Cookieを削除しました!')
resp.delete_cookie('username')
return resp
このように、Flaskでは make_response() で生成したレスポンスオブジェクトに対して set_cookie() を呼ぶことで簡単にCookieを操作できます。
🔐 セッションとは何か?
セッションとは、一連のユーザー操作(ページ遷移など)にまたがって状態を保持する仕組みの総称です。「ログインしてからログアウトするまでの一連の流れ」がセッションのイメージです。
セッションにはCookieを内部的に利用するものも多く、「CookieとSessionは別物」というよりは「SessionはCookieを使って実現することが多い上位の概念」と理解するとスッキリします。
セッションの実装方式は大きく2種類あります。
⚖️ クライアントサイドセッション vs サーバーサイドセッション
① クライアントサイドセッション(Flaskのデフォルト)
たとえ話でいうと、「ガラスケースに入れた荷物」です。中身は(Base64デコードすれば)誰でも見えますが、改ざんするとサーバーに検知されます。
Flaskのデフォルトセッションがこの方式で、セッションデータ全体を署名付きCookie(JWTに近い形式)としてブラウザに保存します。secret_key を使った署名により、データの改ざんは検知できますが、中身はBase64デコードで読めてしまいます。
- ✅ サーバーにデータを保存しなくてよい(スケールしやすい)
- ✅ シンプルで設定が少ない
- ❌ Cookieのサイズ制限(約4KB)がある
- ❌ パスワードなどの機密情報は入れてはいけない
- ❌ セッションを強制失効させにくい
from flask import Flask, session, redirect, url_for, request
app = Flask(__name__)
app.secret_key = 'your-very-secret-key-here' # 必須!署名に使う
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
# ※本来はパスワード検証も行うこと
session['username'] = username # セッションに保存
return redirect(url_for('dashboard'))
return '''
<form method="post">
<input name="username" placeholder="ユーザー名">
<button type="submit">ログイン</button>
</form>
'''
@app.route('/dashboard')
def dashboard():
if 'username' not in session:
return redirect(url_for('login'))
return f'ようこそ、{session["username"]}さん!'
@app.route('/logout')
def logout():
session.clear() # セッションを削除
return 'ログアウトしました'
② サーバーサイドセッション
たとえ話でいうと、「サーバーが管理している鍵付きロッカー」です。セッションデータはサーバー(RedisやDBなど)に保存され、ブラウザには「ロッカーの鍵(セッションID)」だけがCookieとして渡されます。鍵を持っていてもロッカーの中身は見えません。
- ✅ 機密情報をブラウザに渡さない
- ✅ セッションIDを無効化するだけで即座にログアウトできる
- ✅ 大きなデータも保存できる
- ❌ RedisやDBなどのサーバー側ストレージが必要
- ❌ 設定がやや複雑
Flaskでサーバーサイドセッションを実現するには Flask-Session 拡張が便利です。
# pip install Flask-Session redis
from flask import Flask, session
from flask_session import Session
app = Flask(__name__)
# サーバーサイドセッションの設定(Redisを使う例)
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['SESSION_TYPE'] = 'redis' # 保存先をRedisに指定
app.config['SESSION_PERMANENT'] = False
app.config['SESSION_USE_SIGNER'] = True # Cookie側も署名する
import redis
app.config['SESSION_REDIS'] = redis.from_url('redis://localhost:6379')
Session(app) # Flask-Sessionを初期化
@app.route('/set')
def set_session():
session['user_id'] = 42 # RedisにID=42を保存、Cookieにはセッションキーのみ
return 'セッションをサーバー側に保存しました'
@app.route('/get')
def get_session():
user_id = session.get('user_id', 'なし')
return f'user_id: {user_id}'
🛡️ セキュリティの注意点
1. secret_key は必ず強力なものを使う
secret_key はCookieの署名・検証に使われます。短すぎたり推測しやすい文字列を使うと、攻撃者に偽のセッションを作られてしまいます。以下のように生成しましょう。
import secrets
print(secrets.token_hex(32)) # 64文字のランダムな16進数文字列を生成
# 例: 'a3f2...b9c1' のような文字列が出力される
2. HttpOnly フラグ
HttpOnly を設定すると、JavaScriptからCookieにアクセスできなくなります。XSS(クロスサイトスクリプティング)攻撃でCookieを盗まれるリスクを下げられます。Flaskでは set_cookie() に httponly=True を追加します。
3. Secure フラグ
Secure フラグを設定すると、HTTPS通信のときだけCookieが送信されます。本番環境では必ず設定してください。
resp.set_cookie(
'session_id',
value='xxxx',
httponly=True, # JavaScriptからアクセス不可
secure=True, # HTTPSのみ送信
samesite='Lax' # CSRF対策にもなる
)
📊 まとめ比較表
| 項目 | Cookie | クライアントサイドセッション | サーバーサイドセッション |
|---|---|---|---|
| データ保存場所 | ブラウザ | ブラウザ(署名付き) | サーバー(Redis/DB) |
| 中身の可視性 | 見える | Base64で見える | 見えない |
| 改ざん検知 | ❌ | ✅(署名で検知) | ✅ |
| 強制失効 | △(有効期限のみ) | ❌(困難) | ✅(即座に可能) |
| サーバー負荷 | 低い | 低い | やや高い |
| 主なユースケース | 設定保存・トラッキング | 小規模アプリのログイン | 本番アプリのログイン管理 |
🤔 どれを使うべき?
- 📝 学習・プロトタイプ段階 → クライアントサイドセッション(Flaskデフォルト)で十分。設定が少なく手軽に試せます。
- 🔒 ログイン情報・決済など機密データが絡む → サーバーサイドセッションを選びましょう。データがブラウザに漏れません。
- 🌐 言語設定・テーマなどユーザー好みの保存 → Cookieが適しています。長期間保持でき、機密性も不要です。
まとめ
今回はCookie・クライアントサイドセッション・サーバーサイドセッションの違いを解説しました。
- 🍪 Cookie:ブラウザに保存する小さなデータ。見える・書ける「鍵付きロッカー」
- 📦 クライアントサイドセッション:署名でデータを守るが中身は見える「ガラスケース」
- 🔑 サーバーサイドセッション:データをサーバーに隠し、鍵(ID)だけブラウザに渡す
最初はFlaskのデフォルトセッションで動かしてみて、本番環境に移行するタイミングでサーバーサイドセッション+セキュリティフラグの設定を意識するのがおすすめです。ぜひ実際にコードを書いて動かしてみてください!




