aiohttp路由间共享用户数据问题:session在GET/POST间无法互通
解决aiohttp_session跨GET/POST请求session不共享的问题
核心问题分析
你遇到的session不共享问题,主要有两个关键原因:
- 每次服务器重启生成新的加密密钥:代码中每次启动
creat_server都会调用fernet.Fernet.generate_key()生成新密钥,导致之前设置的session cookie无法被新密钥解密,服务器会自动创建新的session。 - (可能的次要原因)session未被正确关联到响应:虽然aiohttp_session中间件会自动处理session保存,但部分响应类型(如
FileResponse)可能需要确保cookie被正确附加。
具体修复步骤
1. 固定加密密钥
不要每次启动服务器生成新密钥,生成一次后固定下来:
# __init__.py async def creat_server(): app = Application() app["db"] = await connect_to_mongodb() app.middlewares.append(db_middleware) # 生成一次密钥后固定(示例密钥,实际请自己生成并替换) # 生成密钥的方法:单独运行一次print(fernet.Fernet.generate_key())并复制结果 fernet_key = b'your-generated-fernet-key-here' secret_key = base64.urlsafe_b64decode(fernet_key) app.router.add_static("/static", os.path.join(os.path.dirname(__file__), "static")) aiohttp_jinja2.setup( app, loader=jinja2.FileSystemLoader( os.path.join(os.path.dirname(__file__), "templates") ), ) setup_routes(app) setup(app, EncryptedCookieStorage(secret_key)) return app
2. 确保session在GET请求中正确保存(可选验证)
在Login视图的GET方法中,显式调用session.save()确保session被写入响应cookie:
# views.py async def get(self): object_id = await init_user(self.request.app["db"]) session = await get_session(self.request) session["object_id"] = object_id await session.save() # 显式保存session print("\n\nhere0", session["object_id"], "\n\n") return FileResponse(os.path.join(BASE_DIR, "login.html"))
3. 验证请求的session一致性
在GET和POST方法中打印session的唯一标识,确认是否为同一个session:
# views.py async def get(self): object_id = await init_user(self.request.app["db"]) session = await get_session(self.request) session["object_id"] = object_id await session.save() print("\n\nhere0 session id:", session.identity, "object_id:", session["object_id"], "\n\n") return FileResponse(os.path.join(BASE_DIR, "login.html")) async def post(self): data = await self.request.post() phone_number = data.get("phone", "") session = await get_session(self.request) print("\n\nhere1 session id:", session.identity, "object_id:", session.get("object_id"), "\n\n") print("Phone number submitted:", phone_number) # add_phone(self.request.app['db'], self.object_id, self.request.form["phone"]) return web.HTTPFound("/welcome-policy")
额外检查项
- 确认浏览器未禁用cookie,POST请求是否携带了GET请求设置的
AIOHTTP_SESSIONcookie。 - 检查
db_middleware是否修改了request或响应对象,导致session cookie被意外移除。
内容的提问来源于stack exchange,提问作者Sina
相关产品推荐
相关产品推荐

