Flask 的 session 与「记住我」cookie 靠什么保证不被篡改?值里到底装了什么?能不能自己算出签名?过期和撤销怎么处理?这篇把 itsdangerous 的算法手工复现一遍。
token = eyJ1aWQiOjQyLCJyb2xlIjoiYWRtaW4ifQ.ar8lEA.YELxoY24nfIUV09xiWo6eGrKZlU
分成 3 段: [34, 6, 27] 字符
第 1 段(payload)base64 解码 → {"uid":42,"role":"admin"}
第 2 段(时间戳)解码为整数 → 1790911760 → 2026-10-02T03:29:20+00:00
第 3 段(签名)解码后的字节数 → 20 (HMAC-SHA1 的输出是 20 字节)
结论:payload 没有加密,任何人拿到 cookie 都能读;签名只保证「没被改过」。上一篇:Cookie 的读写过程;下一篇:Session Cookie 的数据结构;SECRET_KEY 的用途:SECRET_KEY 的用途。
手算签名 = YELxoY24nfIUV09xiWo6eGrKZlU token 里的签名 = YELxoY24nfIUV09xiWo6eGrKZlU 相同: True 派生密钥 = sha1(salt + "signer" + secret_key) 的前 8 字节(十六进制): 095499a3706d5680
原样 → 通过 → {'uid': 42, 'role': 'admin'}
改 payload(签名不变) → BadTimeSignature: Signature b'YELxoY24nfIUV09xiWo6eGrKZlU' does not match
改时间戳(签名不变) → BadTimeSignature: Signature b'YELxoY24nfIUV09xiWo6eGrKZlU' does not match
用另一个密钥验证 → BadTimeSignature: Signature b'YELxoY24nfIUV09xiWo6eGrKZlU' does not match
用另一个 salt 验证 → BadTimeSignature: Signature b'YELxoY24nfIUV09xiWo6eGrKZlU' does not match
截断 → BadTimeSignature: Signature b'YELxoY24nfIUV09xiWo6eG' does not match
去掉签名段 → BadSignature: Signature b'ar8lEA' does not match
随机字符串 → BadSignature: No b'.' found in valuemax_age=10(未过期) → 通过 → x max_age=1(已过期) → SignatureExpired: Signature age 2 > 1 seconds SignatureExpired 的 date_signed = 2026-10-02T03:29:20+00:00 | payload(base64 形式)仍然可取 = b'Ingi' 不传 max_age 时永不过期: x
Set-Cookie 的第一段(名字=值): remember=eyJ1aWQiOjd9.ar8lEg.bluLY8uwxmCwKa1e2BKRZHA9gCw…
GET /me → 200 {'uid': 7}
篡改 payload 后 GET /me → 401 {'error': 'bad signature'}登出(客户端删 cookie)之后,旧 token 被别人拿着继续发 → 200 (服务器无从得知它已「登出」)
payload JSON 字节 token 字符 压缩标记 10 字符的随机十六进制 12 51 未压缩 100 字符的随机十六进制 102 142 以 . 开头(已压缩) 1000 字符的随机十六进制 1002 786 以 . 开头(已压缩) 100 个重复的 x 102 54 以 . 开头(已压缩) 1000 个重复的 x 1002 60 以 . 开头(已压缩)