SECRET_KEY 必须从环境变量读取且禁用硬编码,Session仅存最小必要字段并服务端校验权限,启用SESSION_COOKIE_SECURE和HTTPONLY,显式设置签名时效。

SECRET_KEY 绝不能硬编码在代码里
这是最常被踩的坑:直接写 app.secret_key = '123456' 或者 app.config['SECRET_KEY'] = 'dev-key'。一旦代码进 Git、上生产环境,攻击者拿到源码就能伪造任意 Session,包括管理员身份。
正确做法是强制从环境变量读取,并提供 fallback 仅用于本地开发:
app.secret_key = os.environ.get('SECRET_KEY') or os.urandom(24)- 生产部署时用
export SECRET_KEY=$(openssl rand -base64 32)生成并注入 - 绝对不要把密钥写进
.py、.gitignore也救不了——它已经进过历史提交了
Session 数据本身不加密,只防篡改
Flask 默认用 itsdangerous.URLSafeTimedSerializer 签名,不是加密。Base64 解码后能直接看到原始 JSON 内容,比如 {"user_id": 1001, "role": "admin"} ——攻击者改不了签名,但能读;如果里面存了手机号、邮箱、权限标识,等于裸奔。
所以必须遵守两条铁律:
- Session 里只放最小必要字段:例如
user_id,而不是user_info全量字典 - 敏感逻辑(如“是否为管理员”)必须在服务端查数据库或缓存,不能靠
session.get('role') == 'admin'直接判断 - 若真要存敏感标记,先用
cryptography.fernet加密再塞进 session,别依赖 Flask 默认机制
务必启用 SESSION_COOKIE_SECURE 和 SESSION_COOKIE_HTTPONLY
这两个配置不设,等于把签名后的 Cookie 暴露在明文 HTTP 或 JS 可访问范围内:
-
app.config['SESSION_COOKIE_SECURE'] = True:强制仅 HTTPS 传输,防止中间人窃取 Cookie -
app.config['SESSION_COOKIE_HTTPONLY'] = True:阻止前端 JS 读取document.cookie,缓解 XSS 泄露风险 - 开发时若没配 HTTPS,可加
if not app.debug: ...条件判断,但上线前必须为 True
漏掉任一个,攻击者通过 XSS 或抓包就能拿到有效 Session Cookie,直接冒充用户。
不要依赖默认签名时效,显式控制过期时间
Flask 的 URLSafeSerializer 默认不带时间戳验证,签名永久有效。除非你手动用 timed=True 初始化 serializer,否则 session.permanent = True 只是延长浏览器 Cookie 过期时间,签名本身不过期。
推荐组合方案:
- 设
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=2) - 在登录路由里明确写
session.permanent = True - 同时用
flask_session扩展 + Redis 后端,彻底脱离客户端存储(适合中高安全要求场景)
最危险的是:以为设置了 max_age 就安全了,结果签名没时效,旧 Cookie 拿到新密钥也能验过——密钥轮换后旧 Session 依然有效。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











