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

80 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Changelog: 主动 JWT 续期 —— 消除文件管理器双刷新
**日期**: 2026-06-02
**类型**: 修复 (Bug Fix)
**影响范围**: frontend/src/stores/auth.ts · frontend/src/api/index.ts
---
## 变更摘要
实现客户端 JWT access token 提前续期机制,彻底消除文件管理器"进目录双刷新"问题。
---
## 动机
每次 access token 过期后,`api/index.ts``fetchAuthed()` 会:
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()` 发出实际请求之前加入一个提前续期分支:
```typescript
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.vue``v-select``onMounted` 赋值 `selectedServer` 时会触发 `@update:model-value``onServerChange` 再次 `browse()`;增加 `_initing` 守卫
- `FilesPage.vue``pageReady` 避免首屏短暂显示「请先选择服务器」
- `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. 空目录区不应再闪现「请先选择服务器」(已选服务器时)