session 可以放数据库、缓存、文件,甚至客户端 cookie。各自的存放位置、性能、安全边界是什么?这篇把五种后端都搭起来,直接看数据在哪、cookie 里是什么、读写要多久。
[db ] cookie 值长度 = 32 | django_session 表行数 = 1 | 文件数 = 0 | cookie 内容前 40 字符: z34peyhmzj4soxk66mfcbjn93u46cfm5 [cache ] cookie 值长度 = 32 | django_session 表行数 = 0 | 文件数 = 0 | cookie 内容前 40 字符: omiaeze7bb4aramag9t4wdkdxums7ip8 [cached_db ] cookie 值长度 = 32 | django_session 表行数 = 1 | 文件数 = 0 | cookie 内容前 40 字符: 5nrfvqhfclp5klo0qel2nusljttw6fbe [file ] cookie 值长度 = 32 | django_session 表行数 = 0 | 文件数 = 1 | cookie 内容前 40 字符: 7awrgo6q49lw11ptt3atzgtepe5erh6r [signed_cookies ] cookie 值长度 = 89 | django_session 表行数 = 0 | 文件数 = 0 | cookie 内容前 40 字符: eyJrIjoiYjMxNjFjYTM5YzI5ZWU2MGNmZjYifQ:1
用 SESSION_ENGINE 切换后端。前四种把数据放在服务端,浏览器只拿一个随机 id;signed_cookies 相反,把数据放浏览器里。
不需要密钥就能读出 cookie 里的数据(base64解码): b'{"k":"c21ec1bc98d60d519561"}'
存 1000 字符 → cookie 长度 816
存 3000 字符 → cookie 长度 2343
存 5000 字符 → cookie 长度 3900
存 8000 字符 → cookie 长度 6231 (超过 4096 浏览器会丢弃)
篡改签名后读取: {'k': 0} (读到空 session)用 SECRET_KEY 签名,所以无法伪造;但既不加密,也无法在服务端主动作废(比如「登出所有设备」做不到,第 80 篇的机制是靠密码哈希变化)。
后端 读(ms) 写(ms) db 0.263 0.827 cache 0.092 0.125 cached_db 0.091 0.606 file 0.141 0.384 signed_cookies 0.104 0.152
每次 300 次请求中位数,SQLite 与 LocMem 缓存,没有网络;换成 Redis 缓存 + PostgreSQL,数字会不同(第 98 篇用 Redis 缓存 session)。