# sessions 表字段设计 > 数据模型新增表之三:管理面会话——HttpOnly cookie 里的令牌与服务端状态的对应物。裁决背景见 `docs/design/需求清单.md` §9「访问主体模型」。 | 项目 | 内容 | |------|------| | 状态 | 定稿(2026-10-01) | | 关联 | `docs/design/users表字段设计.md`(`user_id` 指向)· `docs/design/需求清单.md` §9 | | 范围 | 列结构 + 语义 + 写入时机;cookie 参数(SameSite 等)归技术稿;方言映射归数据访问层设计 | | 字段数 | 5 = 1 主键 + 4 业务字段 | --- ## 1. 表定位 - **一行 = 一次活跃登录**——登录成功 INSERT,登出 / 过期 DELETE - 浏览器侧只持有令牌明文(HttpOnly cookie),服务端只存哈希 - **唯一服务对象是管理面(作者)登录**——`user_id` 指向单行的 `users` 表;成员链路**不经此表**(成员凭证是 `members.token_hash` 长期令牌,无会话语义,辨析见 `members表字段设计.md` 3.2) ## 2. 字段清单 | 列 | 类型 | 值来源 | 说明 | |----|------|--------|------| | `id` | bigserial PK | 自增 | | | `user_id` | bigint FK | 登录成功时 | → `users.id` | | `token_hash` | text UNIQUE | 登录成功时 | 会话令牌(随机 256bit)的哈希——cookie 存明文、库存哈希 | | `expires_at` | timestamptz | 登录成功时 | 过期时间(如 7 天);过期即拒绝 | | `created_at` | timestamptz | 登录成功时 | | ## 3. 决策记录(含理由) ### 3.1 服务端会话(查库校验),明确否决 JWT - **JWT 的问题域我们没有**:JWT(无状态令牌)的收益在多服务共享认证、水平扩展免共享存储、海量会话——本项目是单后端、单实例、单管理员,收益一项不占,负担全额缴纳 - **不可吊销是致命伤**:JWT 签发后、过期前无法作废——登出仅是客户端删 cookie(令牌仍有效)、踢下线做不到、改密后旧会话无法失效;业界绕法「短过期 + refresh token」需要服务端存储 refresh token,绕回有状态,JWT 的唯一优势随之蒸发 - **多一个要管理的秘密**:签名密钥的保管、轮换、泄露处置,凭空多一项运维(CFW 形态下多一处 secret 配置) - **本设计即业界最佳实践的翻译**:随机 256bit 令牌、哈希存储、`HttpOnly`/`Secure`/`SameSite`、服务端校验、过期拒绝、登出即吊销——对应 OWASP Session Management Cheat Sheet 逐条要求;「成熟」体现在模式本身。现成认证库的评估归实现期技术稿,模式不变 ### 3.2 令牌哈希存储 拖库不泄会话令牌。 ### 3.3 过期清理为惰性删除 校验命中过期行即删 + 拒绝;不建定时清理任务——过期行占用量级:个位数/月,无清理压力。 ### 3.4 单设备多会话不互斥 同一账号可多处登录(各自行)——单人场景无需「顶号」语义。 ## 4. 写入时机 | 时机 | 动作 | |------|------| | 登录成功 | INSERT(用户名 + PBKDF2 验证密码通过) | | 登出 | DELETE 该行 | | 校验命中过期行 | DELETE + 拒绝(惰性清理) | ## 5. 待定事项 | 事项 | 归属 | |------|------| | cookie 参数(`HttpOnly` / `Secure` / `SameSite=Lax` / Path 限管理面)、会话时长取值 | 技术稿 |