(十二)Flask 会话与签名 Cookie
1. 先保存一项页面偏好
session 可以在一次请求中写值,让同一浏览器后续请求继续带回。Flask 默认把会话数据序列化后放在 Cookie 中,并附上签名。先用不涉及登录的主题偏好观察它。
# 项目文件:demos/cookie_demo.py
import base64
import json
from flask import Flask, session
app = Flask(__name__)
app.secret_key = "temporary-demo-key" # 只用于本文件的临时演示应用。
@app.get("/theme")
def theme():
session["theme"] = "light"
return {"theme": session["theme"]}
client = app.test_client()
client.get("/theme")
cookie = client.get_cookie("session").value
payload = cookie.split(".")[0] # 这份很短的示例载荷没有压缩。
decoded = base64.urlsafe_b64decode(payload + "=" * (-len(payload) % 4))
print(json.loads(decoded)) # 无需签名密钥,也能读出 theme=light。
body, signature = cookie.rsplit(".", 1)
changed = ("A" if signature[0] != "A" else "B") + signature[1:]
client.set_cookie("session", body + "." + changed)
with client.session_transaction() as state:
print("改坏签名后的会话", dict(state))输出先得到 {'theme': 'light'},再得到改坏签名后的空会话。client.get_cookie 读这份 Cookie;短示例的载荷没有压缩,用 Base64 解码即可恢复主题值。修改签名后,Flask 无法验证它,于是按新的空会话处理。
签名检查数据是否被改动,载荷本身可以读取。完整项目只在其中放随机登录编号、CSRF 令牌和短消息,密码留给数据库摘要。SECRET_KEY 是服务器验证签名的依据,项目初始化生成一份并保存在 instance/secret.key,重启继续读取同一份。
2. Cookie 与数据库登录记录一起判断身份
登录后,Cookie 会话中的 sid 指向服务器 logins 表的一条记录;数据库只存它的 SHA-256 摘要。每次请求先验证 Cookie 签名,再查登录记录和到期时间,取得用户。
退出时删除数据库中的登录记录并清空当前会话。这样即使另一客户端保留旧 Cookie 副本,它带回的摘要也已经找不到。Cookie 的清除和服务器记录的撤销是两次具体动作,测试会分别核对。
session.permanent=True 让浏览器 Cookie 有明确到期时间,项目设为一小时;数据库登录记录也保存一小时后的到期时间。Cookie 继续存在而服务器记录已经过期时,本次请求仍会按未登录处理。默认会话行为见 Flask sessions。