概要(Cookie=「ブラウザ側にそっと置くメモ」)
Cookie は一言でいうと、
「サーバーがブラウザにそっと渡して、ブラウザ側に保存してもらう小さなメモ」
です。
ブラウザは、そのメモ(Cookie)を同じサイトにアクセスするときに毎回自動で送ってくれます。
サーバー側は、そのメモを見て
どのユーザーか(ログインセッション)
前回の設定(ダークモードかどうか、言語設定など)
などを判別できます。
ここでは、FastAPI を例にしながら、
Cookie がそもそもどう動くのか
Cookie の読み書きの具体的なコード
セッション的な使い方・注意点
セキュリティ設定(HttpOnly, Secure など)の意味
を、初心者向けに丁寧にかみ砕いて説明します。
Cookie の基本イメージ(サーバーとブラウザのやり取り)
サーバーが「Set-Cookie」、ブラウザが「Cookie」で返す流れ
Cookie のやり取りは、ざっくりこういう流れです。
サーバー → レスポンスヘッダでSet-Cookie: name=value; ...
ブラウザ → その Cookie を保存しておく
次に同じサイトにアクセスするとき、Cookie: name=value; ...
というヘッダを自動で付けて送る
つまり、
一度 Set-Cookie してしまえば、
その後はブラウザが勝手に Cookie を送り続けてくれる
という仕組みです。
ログイン状態の管理や、
ユーザーごとの設定保持などに向いています。
Cookie の中に何を入れるか
Cookie の「中身」は、基本的には単なる文字列です。
だからといって、
ユーザーIDをそのまま入れる
パスワードを入れる
のは、直球すぎて危険です。
実務では多くの場合、
ランダムなセッショントークン
署名付きトークン(JWT など)
を Cookie に入れて、
サーバー側で「このトークンは有効か?」とチェックする形にします。
ここでは、まずシンプルな文字列から始めて、
あとでセキュリティ上の注意も説明します。
FastAPI で Cookie を「セットする」基本(レスポンス側)
set_cookie を使ってレスポンスに Cookie を乗せる
FastAPI では、レスポンスオブジェクトに対して set_cookie を呼び出すことで
Cookie をセットできます。
最小の例から見てみましょう。
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/set-cookie")
def set_cookie():
response = JSONResponse(content={"message": "cookie set"})
response.set_cookie(key="user_id", value="123")
return response
Pythonこのエンドポイントにブラウザからアクセスすると、
レスポンスヘッダに次のようなものが付きます。
Set-Cookie: user_id=123; Path=/
ブラウザは user_id=123 を保存し、
次回から同じドメインへのリクエスト時に自動で送ってくれます。
ここでのポイントを整理します。
set_cookie の key が Cookie 名
value が Cookie の値(文字列)
その他、オプション(有効期限、Secure, HttpOnly など)も指定できる
最初は key と value だけで動きを理解して、
慣れてきたらオプションを増やすと良いです。
値だけでなく、有効期限なども指定できる
Cookie には、有効期限や属性をつけられます。
例えば、「30分で消える Cookie」にしたい場合。
from datetime import timedelta
@app.get("/login")
def login():
response = JSONResponse(content={"message": "logged in"})
response.set_cookie(
key="session_token",
value="RANDOM_TOKEN",
max_age=30 * 60, # 秒単位(30分)
)
return response
Python主に使うパラメータには、こんなものがあります。
max_age
Cookie の有効期間(秒)。ブラウザはこの時間が過ぎたら Cookie を消す。
expires
特定の日時まで有効、という指定もできる(通常は max_age で十分)。
path
そのパス以下にだけ Cookie を送る。通常は / にしておけば全パスに送られる。
domain
どのドメインに対して Cookie を送るか。サブドメインをまたぐときなどに指定。
secure
True にすると HTTPS 接続のときだけ Cookie を送る(http では送らない)。本番では基本 True 推奨。
httponly
True にすると JavaScript(document.cookie)から読めなくなる。XSS 対策としてセッション用 Cookie などに必須級。
特に secure と httponly は安全性に直結するので、
ログイン系の Cookie を扱うときは強く意識してください。
FastAPI で Cookie を「読む」基本(リクエスト側)
Request オブジェクトから Cookie を取り出す
セットした Cookie は、次回以降のリクエストで自動で送られてきます。
FastAPI では、Request 経由で簡単に読めます。
from fastapi import FastAPI, Request
app = FastAPI()
@app.get("/whoami")
def who_am_i(request: Request):
user_id = request.cookies.get("user_id")
return {"user_id": user_id}
Pythonrequest.cookies は dict のようなオブジェクトで、
Cookie 名(key)と値(value)にアクセスできます。
Cookie がない場合は None になるので、
ログインしていない → user_id が None
ログイン済み → user_id が何か入っている
というような判定ができます。
Depends を使って「Cookie チェックを共通化」する
エンドポイントごとに request.cookies を読むのではなく、
Dependency(依存関係)として切り出しておくとスッキリします。
from fastapi import Depends, HTTPException, status
def get_current_user_id(request: Request) -> str:
user_id = request.cookies.get("user_id")
if not user_id:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Not logged in",
)
return user_id
@app.get("/my-page")
def my_page(user_id: str = Depends(get_current_user_id)):
return {"message": f"Hello user {user_id}"}
Pythonこのようにしておくと、
「user_id Cookie がないと 401」
「あるなら user_id をエンドポイントに渡す」
という共通ロジックを get_current_user_id に押し込めます。
ログイン必須の全ての API で、user_id: str = Depends(get_current_user_id) と書くだけで済みます。
Cookie を使った「超シンプルなログイン風フロー」の例
1. ログインエンドポイントで Cookie をセットする
とても単純な「なんちゃってログイン」を考えてみます。
実際のアプリではパスワードチェックなどが入りますが、
ここでは流れを掴むために「ユーザー名を受け取るだけ」にします。
from fastapi import FastAPI, Response
app = FastAPI()
@app.post("/login")
def login(username: str, response: Response):
# 本当はここでユーザー名+パスワードをチェックする
response.set_cookie(key="username", value=username, httponly=True)
return {"message": f"logged in as {username}"}
Pythonポイントは Response を引数に受け取っていることです。
FastAPI は、引数に Response 型を入れると、
レスポンスオブジェクトを注入してくれます。
そこに対して set_cookie を呼び出して、Cookie を設定します。
2. ログイン後のページで Cookie を読む
次に、「ログインしている前提で動くエンドポイント」を作ります。
from fastapi import Request, HTTPException, status
@app.get("/dashboard")
def dashboard(request: Request):
username = request.cookies.get("username")
if not username:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Not logged in",
)
return {"message": f"Welcome, {username}"}
Pythonブラウザ側の流れとしては、
POST /login?username=taro などを叩く
レスポンスで Set-Cookie: username=taro を受け取る
ブラウザが Cookie を保存
その後 /dashboard にアクセスするとき、
ブラウザが Cookie: username=taro を自動で付けて送る
サーバー側では、
その Cookie を見て「taro としてログインしている」と判断します。
これが Cookie を使った認証の超基本イメージです。
実務では、username を直接 Cookie に入れるより、
ランダムなセッショントークン
署名付きのセッションID
などを入れて、
サーバー側で user_id と紐付ける形にします。
Cookie を使うときのセキュリティ上の注意(ここは少し深掘り)
1. センシティブな情報を生のまま入れない
Cookie は、基本的にクライアント側に丸見えです。
開発者ツールから簡単に中身が見えてしまいます。
そのため、
パスワード
生の個人情報(住所、電話番号など)
を直接入れるのはNGです。
ユーザーIDくらいならまだしも、「セッション用のランダムなトークン」を入れて、
サーバー側の DB で実体情報と紐付ける、という設計のほうが安全です。
2. HttpOnly を付けて JavaScript から読めなくする
XSS(クロスサイトスクリプティング)攻撃で、
サイト内に悪意ある JavaScript が紛れ込んだ場合、
document.cookie で Cookie が盗まれるリスクがあります。
ログインセッション用 Cookie などは、
必ず httponly=True を付けておくのが望ましいです。
response.set_cookie(
key="session_token",
value="RANDOM",
httponly=True,
)
PythonHttpOnly を付けると、
JavaScript からは Cookie が読めなくなります(ブラウザがブロックする)。
サーバーとの通信には自動で付くので、認証には支障ありません。
3. Secure を付けて HTTPS のときだけ送る
secure=True を付けると、
HTTP では Cookie を送らず、HTTPS 接続時だけ送るようになります。
平文 HTTP のままだと、
ネットワーク上で Cookie が盗み見される可能性があります。
本番でログインセッションを扱うなら、
HTTPS(TLS)必須
セッション Cookie は secure=True
はほぼセットで考えるべきです。
Cookie と Bearer トークン(ヘッダ)との違いのイメージ
Cookie:ブラウザに任せて自動送信される「小さなメモ」
Cookie は、主にブラウザが使う仕組みです。
一度 Set-Cookie を受け取れば、
ブラウザが自動で Cookie を付けてくれるので、
フロント側で毎回トークンをヘッダにセットする必要がありません。
Web アプリ(ブラウザ+サーバー)の世界では、
セッション管理に非常によく使われます。
Bearer トークン:クライアントが自分でヘッダに付ける「入館証」
一方、Bearer トークンは、
クライアントが自分で Authorization: Bearer ... をセットします。
ブラウザ・モバイル・他のサーバーなど、
いろいろなクライアントで使いやすく、API 用途に向いています。
どっちが絶対にいい、という話ではなく、
ブラウザだけを相手にする Web アプリ → Cookie セッションが自然
外部サービスからも叩かれる API → Bearer トークン(ヘッダ)が自然
という使い分けが多いです。
FastAPI はどちらにも対応しやすいので、
アプリの性質に合わせて選ぶ感じです。
まとめ(Cookie は「ブラウザと仲良くするための持ち物」)
Python Web フレームワーク(FastAPI)での Cookie を整理すると、こうなります。
- Cookie は、サーバーが Set-Cookie でブラウザに渡し、ブラウザが次回以降のリクエストで自動的に Cookie ヘッダとして送り返してくれる「小さなメモ」。
- FastAPI ではレスポンスの
set_cookieで Cookie をセットし、Request のrequest.cookiesから読むことができる。ログインセッションやユーザー設定などの継続的な情報に向いている。 - Dependency(get_current_user など)として Cookie チェックを切り出すと、「ログイン必須」のエンドポイントに共通の認証ロジックを簡単に適用できる。
- セッション系の Cookie には、HttpOnly や Secure を付けることが重要で、生のパスワードやセンシティブ情報を直接 Cookie に入れないようにする。
- Cookie はブラウザ主体、Bearer トークンはクライアント主体(ヘッダ)という違いがあり、Web アプリ寄りなら Cookie、API 利用が多いなら Bearer という選び分けがよく使われる。
