bigywater.tech
Django · 72

Session 登录状态如何保存

用户的登录状态放在哪里?每个请求为它付出多少次查询?过期了会被自动清掉吗?这篇看默认的数据库 session 后端,把创建时机、表内容、cookie 属性、查询数和过期都验证一遍。

用到才创建
只读 session 不创建行也不发 Set-Cookie;写入才创建
14 天固定
SESSION_COOKIE_AGE 默认 1209600 秒;SESSION_SAVE_EVERY_REQUEST 默认 False,不续期
不自动清理
过期的 session 行仍留在表里,要运行 clearsessions

什么时候创建

实测 · 本机执行输出
GET /nothing/  Set-Cookie: False session 表行数: 0
GET /ro/       Set-Cookie: False session 表行数: 0
GET /read/     Set-Cookie: False session 表行数: 0
GET /set/      Set-Cookie: True  session 表行数: 1

这也是「不登录的访客不产生 session 行」的原因;但一旦有代码往 session 里写(比如 messages 框架、CSRF 用 session 时),就会给每个访客创建一行。

表里与 cookie

实测 · 本机执行输出
session_key 长度 = 32  expire_date 距现在 = 14.0 天
session_data(前 60 字符)= eyJjYXJ0IjpbMSwyLDNdfQ:1xBtdR:nx5w9m_N2jjqQWTShcikaHgR1Vwbc7 …
解码后: {'cart': [1, 2, 3]}
Cookie 属性: {'httponly': True, 'samesite': 'Lax', 'max-age': 1209600, 'path': '/'}

session_data 的格式是「base64 的 JSON : 时间戳 : 签名」(实测),所以数据库里的内容不能被随便伪造,但也不是加密的(base64 可读)。

查询与写入

实测 · 本机执行输出
/read/(只读):查询 = 1
    SELECT "django_session"."session_key", "django_session"."session_data", "django_session"."expire_dat
/set/(修改):查询 = 4
    SELECT "django_session"."session_key", "django_session"."session_data", "django_session"."expire_dat
    BEGIN
    UPDATE "django_session" SET "session_data" = 'eyJjYXJ0IjpbMSwyLDNdfQ:1xBtdS:1D6ER3uNfryST9BtuJ4_Ai4R
    COMMIT
/nothing/(不访问 session):查询 = 0

Django 会在响应阶段判断 session.modified,才决定是否写库。

默认值

实测 · 本机执行输出
SESSION_COOKIE_AGE = 1209600 秒 = 14 天;SESSION_SAVE_EVERY_REQUEST = False ;SESSION_COOKIE_HTTPONLY = True ;SESSION_COOKIE_SAMESITE = Lax ;SESSION_EXPIRE_AT_BROWSER_CLOSE = False

要「用户活跃就续期」需要 SESSION_SAVE_EVERY_REQUEST = True(每个请求都写库,本文没有测它的代价)。

过期与清理

实测 · 本机执行输出
过期后表里行数: 1 ; 用该 cookie 读取: {'cart': None}
clearsessions 之后表里行数: 0

数据库后端的表会一直增长。定时任务运行 clearsessions(cron / celery beat)。缓存后端靠缓存自己的过期。

分步演示:登录状态的存放

Session 保存登录状态
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动。SQLite 后端;cookie 属性来自 Set-Cookie 头
    • 没有验证:SESSION_SAVE_EVERY_REQUEST=True 的代价、SESSION_COOKIE_SECURE 与 HTTPS、session 序列化器(JSON vs pickle)的选择、session 数据大小的上限(见第 79 篇的 cookie 后端)
    京ICP备2026067502号-1京公网安备11010502063487号