Python 现代开发学习笔记

(十二)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,重启继续读取同一份。

写入 theme 后序列化为可读取载荷并附签名,浏览器带回 Cookie,签名正确恢复数据,改坏后得到空会话

2. Cookie 与数据库登录记录一起判断身份

登录后,Cookie 会话中的 sid 指向服务器 logins 表的一条记录;数据库只存它的 SHA-256 摘要。每次请求先验证 Cookie 签名,再查登录记录和到期时间,取得用户。

退出时删除数据库中的登录记录并清空当前会话。这样即使另一客户端保留旧 Cookie 副本,它带回的摘要也已经找不到。Cookie 的清除和服务器记录的撤销是两次具体动作,测试会分别核对。

session.permanent=True 让浏览器 Cookie 有明确到期时间,项目设为一小时;数据库登录记录也保存一小时后的到期时间。Cookie 继续存在而服务器记录已经过期时,本次请求仍会按未登录处理。默认会话行为见 Flask sessions。

Cookie 签名校验通过后读 sid,计算摘要查 logins,核对到期取得用户;退出删除记录后旧 Cookie 再请求无法取得身份

笔记正文与全部题解 · Ctrl / ⌘ K