Files
Nexus/docs/changelog/2026-06-02-proactive-jwt-refresh.md
T
2026-06-02 04:36:46 +08:00

2.8 KiB
Raw Blame History

Changelog: 主动 JWT 续期 —— 消除文件管理器双刷新

日期: 2026-06-02
类型: 修复 (Bug Fix)
影响范围: frontend/src/stores/auth.ts · frontend/src/api/index.ts


变更摘要

实现客户端 JWT access token 提前续期机制,彻底消除文件管理器"进目录双刷新"问题。


动机

每次 access token 过期后,api/index.tsfetchAuthed() 会:

  1. 先发出一次业务请求 → 服务端返回 401
  2. 触发 /auth/refresh 获取新 token
  3. 用新 token 重发同一业务请求

导致每次进入目录产生 2 次 /api/sync/browse 请求,页面可见"双刷新"(_browseSeq 虽可防止旧数据覆盖,但无法消除 2 次请求本身)。


方案

frontend/src/stores/auth.ts

  • 新增 decodeJwtExp(jwt) 工具函数:不验签地从 JWT Payload 解码 exp 字段(秒)
  • 新增 tokenExp computed:返回当前 token 的过期 unix 秒,无 token 时为 0
  • 新增 isTokenExpiringSoon(thresholdSec = 300) 方法:当距过期 < thresholdSec 秒时返回 true

frontend/src/api/index.ts

fetchAuthed() 发出实际请求之前加入一个提前续期分支:

if (!_retry && !AUTH_SKIP_REFRESH.has(path) && auth.token && auth.isTokenExpiringSoon(300)) {
  await tryRefreshSession()
}

若 token 将在 5 分钟内过期,先刷新再发请求,完全跳过"401 → 重试"路径。 原有的 401 兜底重试逻辑保留不变(处理极端并发或时钟偏差场景)。


涉及文件

文件 变更类型
frontend/src/stores/auth.ts 新增 decodeJwtExp / tokenExp / isTokenExpiringSoon
frontend/src/api/index.ts fetchAuthed 中新增提前续期分支

是否需要迁移 / 重启

  • 前端: 需重新 vite build 后部署到服务器
  • 后端: 无变更,无需重启
  • 数据库: 无变更

追加修复(2026-06-02 续)

  • FilesPage.vuev-selectonMounted 赋值 selectedServer 时会触发 @update:model-valueonServerChange 再次 browse();增加 _initing 守卫
  • FilesPage.vuepageReady 避免首屏短暂显示「请先选择服务器」
  • FilesPage.vue:同路径并发 browse() 合并为单次 in-flight 请求
  • 部署须执行 deploy/prune_frontend_assets.py 清理服务器上残留的旧 hash chunk(否则浏览器可能仍加载旧 FilesPage-*.js

验证方式

  1. 登录后等待 access token 接近过期(或手动修改 token exp 为近期时间)
  2. 进入文件管理器浏览目录
  3. 打开 DevTools Network 过滤 /sync/browse
  4. 预期:每次进目录只有 1 条 /sync/browse 请求,不再出现 401 后重试的第 2 条
  5. 空目录区不应再闪现「请先选择服务器」(已选服务器时)