FastAPI+Starlette中间件会话问题:重定向后无法访问会话数据
FastAPI + Azure B2C 会话用户数据丢失问题排查与解决
核心排查方向
- 中间件冲突干扰会话处理
- SessionMiddleware 配置错误
- MSAL 缓存读写逻辑异常
- Cookie 跨域/属性设置问题
- 重定向时会话未正确提交
具体解决方案
1. 移除自定义会话中间件,避免与Starlette默认中间件冲突
你的代码中同时使用了Starlette的SessionMiddleware和自定义的session_middleware,后者会覆盖默认的会话cookie处理逻辑,导致会话数据无法正确持久化。直接删除自定义中间件:
# 删掉这段冗余代码 @app.middleware("http") async def session_middleware(request: Request, call_next): response = await call_next(request) session = request.cookies.get('session') if session: response.set_cookie(key='session', value=session, httponly=True) return response
2. 修正SessionMiddleware配置
确保会话密钥安全,同时配置正确的cookie属性:
- 替换硬编码的
secret_key为随机生成的密钥(从环境变量读取更安全) - 根据环境设置
secure属性(生产环境HTTPS下开启,本地测试可关闭) - 合理设置
max_age和same_site
修改后的配置示例:
import os import secrets app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET_KEY", secrets.token_hex(32)), max_age=86400, # 会话有效期1天 httponly=True, secure=os.getenv("ENVIRONMENT") == "production", # 生产环境开启HTTPS same_site="lax")
3. 验证MSAL缓存读写逻辑
检查ad_helpers.py中的load_cache和save_cache实现,确保它们正确操作会话中的缓存数据:
# ad_helpers.py 中正确的缓存读写示例 import msal def load_cache(request: Request): cache = msal.SerializableTokenCache() if request.session.get("msal_cache"): cache.deserialize(request.session["msal_cache"]) return cache def save_cache(request: Request, cache: msal.SerializableTokenCache): if cache.has_state_changed: request.session["msal_cache"] = cache.serialize()
如果缓存未正确序列化/反序列化,会导致会话中的用户数据无法被后续请求读取。
4. 检查重定向与会话提交
确保在oauth_callback中设置request.session['user']后,会话数据被正确提交:
- 确认
user_info = result.get('id_token_claims')返回有效数据(可通过日志验证) - 确认
request.session['user']赋值完成后再执行重定向
5. 浏览器端Cookie验证
- 完成OAuth回调后,打开浏览器开发者工具(F12),查看
Application标签下的Cookies,确认是否存在sessioncookie - 访问
/user-profile时,查看Network标签下的请求头,确认Cookie字段包含session值 - 如果Cookie未被携带,检查:
- 是否在HTTP环境下设置了
secure=True(需改为False) same_site设置是否与前端请求模式匹配(跨域场景可尝试same_site="none",但需配合secure=True)- 域名是否一致(跨域时需配置
domain参数)
- 是否在HTTP环境下设置了
6. 临时关闭自动重载测试
如果使用uvicorn --reload运行服务,重载会导致进程重启,会话数据丢失。测试时关闭重载,直接用uvicorn main:app启动服务。
内容的提问来源于stack exchange,提问作者Dominik Borkowski
相关产品推荐
相关产品推荐

