bigywater.tech
Flask · 48

Session Cookie 的数据结构

session 里的东西到底存在哪?装的是什么格式?不用密钥能不能读出来?为什么我改了 session 却没有新的 Set-Cookie?这篇把 cookie 解开,逐项验证。

0 个
读取 session cookie 的 payload 所需的密钥个数(只需 base64,可明文读取)
4093
超过它会触发警告的 cookie 大小(字节)
{}
签名不对时读到的 session(不抛异常)

一个 session cookie

实测 · 本机执行输出
  Set-Cookie: session=eyJuIjoxLCJ1c2VyIjoiYW5uIn0.ar8lSw.iTT4dPfhvFyMd5C6j3OTHgi3MeI; HttpOnly; Path=/
  cookie 值分 3 段;压缩=False;payload = {"n":1,"user":"ann"};签发时间 = 2026-10-02T03:30:19+00:00

上一篇:Signed Cookie;下一篇:Range 请求与断点下载;SECRET_KEY 的专题:SECRET_KEY 的用途;安全属性:Session Cookie 安全属性。

TaggedJSON

实测 · 本机执行输出
  payload = {"bytes":{" b":"AP9hYg=="},"dt":{" d":"Fri, 02 Oct 2026 12:00:00 GMT"},"list":[1,{"a":{" t":[3,4]}}],"markup":{" m":"<b>x</b>"},"n":1,"tuple":{" t":[1,2]},"user":"ann","uuid":{" u":"000000000000000000000000000000ff"}}
  session 里的真实类型: {'bytes': 'bytes', 'dt': 'datetime', 'list': 'list', 'markup': 'Markup', 'tuple': 'tuple', 'uuid': 'UUID'}

permanent

实测 · 本机执行输出
  非 permanent: HttpOnly; Path=/
  permanent   : Expires=Mon, 02 Nov 2026 03:30:19 GMT; HttpOnly; Path=/
  PERMANENT_SESSION_LIFETIME = 31 days, 0:00:00

重发 Set-Cookie

实测 · 本机执行输出
  非 permanent:只读一下                     → 不发
  非 permanent:修改                       → 发 Set-Cookie
  permanent:只读一下                       → 发 Set-Cookie
  permanent + REFRESH=False:只读一下       → 不发

登出

实测 · 本机执行输出
  Set-Cookie: session=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; HttpOnly; Path=/

大小与压缩

实测 · 本机执行输出
  随机十六进制     100 字符 → cookie 值   151 字节 | 已压缩 | 警告 0 条
  随机十六进制    1000 字符 → cookie 值   803 字节 | 已压缩 | 警告 0 条
  随机十六进制    3000 字符 → cookie 值  2318 字节 | 已压缩 | 警告 0 条
  随机十六进制    5000 字符 → cookie 值  3878 字节 | 已压缩 | 警告 0 条
  随机十六进制    8000 字符 → cookie 值  6235 字节 | 已压缩 | 警告 1 条
  重复的 x      100 字符 → cookie 值    62 字节 | 已压缩 | 警告 0 条
  重复的 x     1000 字符 → cookie 值    68 字节 | 已压缩 | 警告 0 条
  重复的 x     5000 字符 → cookie 值    87 字节 | 已压缩 | 警告 0 条

篡改

实测 · 本机执行输出
  原样                         → 200 {'n': 1, 'user': 'ann'}
  改 payload 第 5 个字符          → 200 {}
  换成别的密钥签的                   → 200 {}

签名参数

实测 · 本机执行输出
  salt = cookie-session | key_derivation = hmac | digest_method = _lazy_sha1 | serializer = TaggedJSONSerializer

分步演示

Session Cookie
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动
    • 没有验证:服务端 session(Flask-Session 等扩展)与客户端 session 的对比、SESSION_COOKIE_PARTITIONED、SECRET_KEY_FALLBACKS 在 session 上的轮换(见第 187 篇)、session 在多个 worker 之间共享(客户端 session 天然共享,只要密钥相同)
    京ICP备2026067502号-1京公网安备11010502063487号