05006cb5df
登录 30 天会话 hash 持久化到 admin_refresh_tokens;启动从 MySQL 回填 Redis, Redis 重启后会话仍可 refresh。 Co-authored-by: Cursor <cursoragent@cursor.com>
1.6 KiB
1.6 KiB
2026-06-07 — 登录 Refresh Token Redis + MySQL 双写
摘要
30 天登录会话的 refresh token 改为 先写 Redis、再写 MySQL;API 启动时从 MySQL 回填 Redis,Redis 重启/flush 后会话不丢失。
动机
此前 refresh token 仅存 Redis Set(refresh_tokens:{admin_id}),Redis 重载或 flush 后 HttpOnly Cookie 仍在但服务端认不出,用户被迫重新登录。
变更
| 文件 | 说明 |
|---|---|
server/domain/models/__init__.py |
表 admin_refresh_tokens(token_hash + expires_at) |
server/infrastructure/database/refresh_token_repo.py |
MySQL CRUD / rotate / 按 admin 清理 |
server/application/services/auth_service.py |
双写、校验 MySQL 回退、rotate 双端 |
server/application/services/refresh_token_hydration.py |
启动 hydration + 清理过期行 |
server/main.py |
init_redis 后 hydration |
server/api/dependencies.py |
注入 refresh_token_repo |
server/api/auth.py |
改密走 _delete_all_refresh_tokens 双端清理 |
server/infrastructure/database/migrations.py |
CREATE TABLE 迁移 |
tests/test_refresh_token_persistence.py |
双写 / MySQL 回退 / 双删 |
配置
- 有效期仍由
JWT_REFRESH_TOKEN_EXPIRE_DAYS(默认 30)控制 - Access Token 仍约 60 分钟,靠 refresh 续期
迁移 / 重启
需重启 API;新表自动 create_all + schema migration。
验证
pytest tests/test_refresh_token_persistence.py tests/test_auth_refresh_reuse.py -q
登录 → 重启 Redis → 刷新页面应仍可续期(hydration + MySQL 回退)。