FastAPI Cookie 与 Session 详解
在 Web 开发中,HTTP 是无状态协议——服务端默认不会记住客户端的上一次请求。Cookie 和 Session 正是为了解决"记住用户"这一需求而生的。FastAPI 基于 Starlette,提供了便捷的 Cookie 操作接口和 Session 中间件支持。本文系统讲解从 Cookie 基础到 Session 实战的全链路知识。
Cookie 的基本概念
Cookie 是服务端通过 Set-Cookie 响应头写入浏览器的一小段文本数据(通常不超过 4KB)。浏览器收到后会自动保存,并在后续请求中通过 Cookie 请求头自动回传。一个典型的 Cookie 工作流程:
客户端请求 → 服务端 Set-Cookie: user_id=abc → 浏览器保存
后续请求 → 浏览器自动带 Cookie: user_id=abc → 服务端识别用户
读取 Cookie
FastAPI 读取 Cookie 极其简单——直接将参数名声明为 Cookie 类型即可:
from fastapi import FastAPI, Cookie
from typing import Optional
app = FastAPI()
@app.get("/profile")
async def get_profile(user_token: Optional[str] = Cookie(None)):
if user_token is None:
return {"message": "未登录"}
return {"user_token": user_token, "message": "欢迎回来"}
访问 http://localhost:8000/profile ——如果浏览器没有名为 user_token 的 Cookie,user_token 就是 None,返回"未登录"。
如果 Cookie 名和 Python 变量名不同(比如 Cookie 名带横线),可以用 alias 参数:
@app.get("/items/")
async def read_items(
session_id: Optional[str] = Cookie(None, alias="session-id")
):
return {"session_id": session_id}
设置 Cookie
设置 Cookie 需要操作 Response 对象。FastAPI 提供了 Response 参数注入,调用 set_cookie() 即可:
from fastapi import FastAPI, Response
from datetime import datetime, timedelta
app = FastAPI()
@app.post("/login")
async def login(username: str, response: Response):
# 登录逻辑(此处简化)
token = f"token_{username}_{datetime.now().timestamp()}"
# 设置 Cookie
response.set_cookie(
key="user_token",
value=token,
max_age=3600, # 有效期,单位秒
httponly=True, # 禁止 JS 读取,防 XSS
secure=True, # 仅 HTTPS 传输
samesite="lax", # 防 CSRF
path="/", # Cookie 生效路径
)
return {"message": "登录成功"}
set_cookie 参数详解
| 参数 | 说明 | 推荐值 |
|---|---|---|
key |
Cookie 名称 | 自定义 |
value |
Cookie 值(字符串) | — |
max_age |
过期时间(秒),优先级高于 expires |
按需 |
expires |
具体的过期 datetime | — |
path |
生效路径,/ 表示全站 |
/ |
domain |
生效域名,默认当前域 | — |
secure |
仅 HTTPS 传输 | True |
httponly |
禁止 JavaScript 访问 | True |
samesite |
跨站请求控制:lax / strict / none |
lax |
安全提示:生产环境务必开启 httponly、secure 和 samesite。httponly 能防止 XSS 窃取 Cookie,samesite=lax 能防御大部分 CSRF 攻击。
删除 Cookie
删除 Cookie 的本质是设置一个立即过期的同名 Cookie:
@app.post("/logout")
async def logout(response: Response):
response.delete_cookie(
key="user_token",
path="/",
secure=True,
httponly=True,
samesite="lax",
)
return {"message": "已退出登录"}
delete_cookie() 内部会设置 max_age=0 和 expires=0,浏览器收到后就会删除该 Cookie。注意删除时的 path、domain 等参数必须和设置时一致,否则浏览器不会删除。
自定义 Response 中操作 Cookie
如果你的路由函数返回的不是简单字典,而是自定义 Response,同样可以操作 Cookie:
from fastapi.responses import JSONResponse
@app.post("/custom-login")
async def custom_login(username: str):
token = f"custom_token_{username}"
content = {"message": "登录成功"}
response = JSONResponse(content=content)
response.set_cookie(
key="user_token",
value=token,
max_age=3600,
httponly=True,
secure=True,
samesite="lax",
)
return response
Session 的实现
Session 本质上是"存储在服务端的用户数据",客户端只持有一个 Session ID(通常放在 Cookie 中)。FastAPI 没有内置 Session 机制,但 Starlette 提供了 SessionMiddleware,开箱即用。
安装与配置
SessionMiddleware 需要 itsdangerous 库用于签名:
pip install itsdangerous
在 FastAPI 应用中添加 Session 中间件:
from fastapi import FastAPI, Request
from starlette.middleware.sessions import SessionMiddleware
app = FastAPI()
# 添加 Session 中间件
app.add_middleware(
SessionMiddleware,
secret_key="your-secret-key-change-in-production",
session_cookie="session_id", # Cookie 名称,默认 "session"
max_age=3600, # 过期秒数,默认 14 天
same_site="lax",
https_only=False, # 开发环境 False,生产环境 True
)
@app.get("/set-session")
async def set_session(request: Request):
request.session["username"] = "张三"
request.session["role"] = "admin"
return {"message": "Session 已设置"}
@app.get("/get-session")
async def get_session(request: Request):
username = request.session.get("username", "游客")
role = request.session.get("role", "anonymous")
return {"username": username, "role": role}
@app.get("/clear-session")
async def clear_session(request: Request):
request.session.clear()
return {"message": "Session 已清除"}
SessionMiddleware 工作原理
- 读取请求 Cookie 中名为
session(或自定义名)的值 - 用
secret_key验签并解密,还原为 Python 字典挂载到request.session - 路由函数可以像操作普通字典一样读写
request.session - 响应时,中间件将
request.session序列化、签名后写回 Cookie
核心要点:Session 数据是加密签名后存在 Cookie 中的(客户端 Session),而不是存在服务端内存或数据库。优点是无需服务端存储,天然支持分布式;缺点是 Cookie 有 4KB 大小限制,且不应存放敏感数据(加密不等于安全,密钥泄露即全部暴露)。
实操:Cookie + Session 实现登录态
下面是一个完整的登录验证示例,展示 Cookie 和 Session 如何配合使用:
from fastapi import FastAPI, Request, Response, HTTPException, Cookie
from starlette.middleware.sessions import SessionMiddleware
from typing import Optional
app = FastAPI()
app.add_middleware(
SessionMiddleware,
secret_key="super-secret-key-2026",
session_cookie="sid",
max_age=86400, # 24 小时
same_site="lax",
)
# 模拟的用户数据库
fake_users = {"admin": "password123"}
@app.post("/api/login")
async def api_login(
request: Request,
response: Response,
username: str,
password: str,
):
"""用户登录接口"""
if username not in fake_users or fake_users[username] != password:
raise HTTPException(status_code=401, detail="用户名或密码错误")
# 将用户信息存入 Session
request.session["user"] = username
request.session["login_time"] = "2026-07-19"
# 同时设置一个独立的持久化 Cookie(比如"记住我"功能)
response.set_cookie(
key="remember_me",
value="1",
max_age=86400 * 30, # 30 天
httponly=True,
secure=True,
samesite="lax",
)
return {"message": f"欢迎 {username}!登录成功"}
@app.get("/api/me")
async def get_current_user(request: Request):
"""获取当前登录用户信息"""
user = request.session.get("user")
if user is None:
raise HTTPException(status_code=401, detail="请先登录")
return {
"username": user,
"login_time": request.session.get("login_time"),
}
@app.post("/api/logout")
async def api_logout(request: Request, response: Response):
"""用户退出登录"""
request.session.clear() # 清除 Session
response.delete_cookie("remember_me") # 清除记住我 Cookie
return {"message": "已退出登录"}
测试流程:POST /api/login → 浏览器自动保存 Cookie → GET /api/me 返回用户信息 → POST /api/logout 清除所有状态。
Cookie vs Session 对比
| 维度 | Cookie | Session (Starlette) |
|---|---|---|
| 数据存储位置 | 客户端浏览器 | Cookie 中(加密签名) |
| 容量限制 | 每个 Cookie 约 4KB | 受 Cookie 总大小限制 |
| 安全性 | 明文,可被用户篡改 | 加密签名,篡改可检测 |
| 过期控制 | max_age / expires |
max_age(中间件参数) |
| 适用场景 | 记住偏好、跟踪标识 | 登录态、用户数据 |
小结
Cookie 和 Session 是 Web 开发中管理用户状态的两大基石:
- Cookie 适合存放轻量、非敏感的客户端标识,通过
set_cookie()设置、Cookie()读取 - Session 通过
SessionMiddleware实现,数据加密签名存储在 Cookie 中,适合存放登录态等需要防篡改的信息 - 安全是底线:生产环境务必启用
httponly、secure、samesite,且secret_key绝对不可泄露
掌握了 Cookie 和 Session,你就能构建出有"记忆"的 Web 应用——记住用户偏好、维护登录状态、实现购物车功能,全都离不开它们。
- 点赞
- 收藏
- 关注作者
评论(0)