fix: token刷新数据源统一+非空断言修复+并发竞态锁 #1416

Merged
xiaoxia merged 2 commits from fix/token-refresh-bugs into develop 2026-08-18 13:42:32 +08:00
Owner

修复 token 刷新 3 个问题:数据源不一致、非空断言崩溃、并发竞态

修复 token 刷新 3 个问题:数据源不一致、非空断言崩溃、并发竞态
xiaoxia added 1 commit 2026-08-18 12:49:33 +08:00
fix: token刷新数据源统一+非空断言修复+并发竞态锁
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 41s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m43s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m48s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m49s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m8s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m35s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 2m6s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m27s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 5m22s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 7s
AI Code Review / AI Code Review (pull_request) Has been cancelled
0f321c62c1
Bug 1 — 数据源统一:
- scheduleProactiveRefresh() 中 accessToken 和 refreshToken 统一从 Zustand store 读取
- 修复前:accessToken 从 localStorage 读,refreshToken 从 Zustand 读(不一致)
- 修复后:两者都从 useAuthStore.getState() 读取(单一数据源)

Bug 2 — 非空断言修复:
- 移除 client.ts 和 tokenRefresh.ts 中的 user! 强制非空断言
- executeTokenRefresh() 在刷新前检查 user 是否为空,为空则跳过刷新
- client.ts 401 处理中,executeTokenRefresh() 返回 null 时直接登出

并发竞态修复:
- 新增 executeTokenRefresh() 共享函数,带 activeRefreshPromise 锁
- 主动刷新(setTimeout)和被动刷新(401 拦截器)共用同一把锁
- 多个组件同时触发刷新时,只发一次请求,后续调用复用 Promise

测试更新:
- client.test.ts 适配新逻辑,mock executeTokenRefresh 替代直接 mock refreshAccessToken
- 43 个测试全部通过

🚀 预览环境已部署

项目 详情
PR号 #1416
预览链接 https://pr-1416.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1416 | | 预览链接 | [https://pr-1416.preview.xiaoxiajianji.com](https://pr-1416.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia added 1 commit 2026-08-18 12:55:52 +08:00
style: format client.test.ts with prettier
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 38s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 1m43s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 1m46s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 1m46s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m8s
AI Code Review / AI Code Review (pull_request) Failing after 1m59s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m36s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 2m12s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m55s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 2m32s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 6m33s
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 33s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 42s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Waiting to run
d54767c929
Collaborator

【阻塞级判定】

  • 是否存在阻塞级问题:是
  • 阻塞级问题数量:2 个

📊 审查概览

  • 整体评价:需修改
  • 建议级问题数量:0 个

🔴 阻塞级问题(必须修复)

  1. [apps/web/src/api/auth/tokenRefresh.ts: 39-77] 用户登出时存在竞态条件导致重新登录

    • 问题类型:逻辑bug / 安全漏洞
    • 问题描述:cancelProactiveRefresh 函数仅清除了定时器,但没有取消正在进行的 executeTokenRefresh 操作。如果用户在 Token 刷新请求进行中(activeRefreshPromise pending)点击登出,虽然 clearAuth 会清空 Store,但刷新请求仍在后台运行。一旦刷新请求成功返回,executeTokenRefresh 中的 setAuth 会被执行,导致用户被重新“自动登录”,绕过了用户的登出意图。
    • 修改建议:引入一个取消标志(如 isRefreshCancelled)。在 cancelProactiveRefresh 中将该标志设为 true。在 executeTokenRefreshtry 块中,调用 setAuth 之前检查该标志,如果已取消则跳过更新状态。
  2. [apps/web/src/api/client.ts: 110] 刷新失败后的重定向路径不一致

    • 问题类型:逻辑bug
    • 问题描述:当 executeTokenRefresh 返回 null(即无 user 或 refreshToken)时,代码将页面重定向到 "/"(首页)。而在 tokenRefresh.tsexecuteTokenRefresh 内部 catch 块中,刷新失败是重定向到 "/login"。这种不一致可能导致在 401 错误场景下,用户被错误地导向首页(可能再次触发 401 循环或显示访客视图),而不是统一的登录页。
    • 修改建议:将 window.location.href = "/" 修改为 window.location.href = "/login",保持认证失败行为的一致性。

💡 改进建议(不阻塞合并)

良好实践

  • 引入 activeRefreshPromise 锁机制有效解决了并发刷新导致的 Token 覆盖问题。
  • 测试用例更新及时,覆盖了新的刷新逻辑路径。

格式检查通过 | 逻辑审查需修改 | 性能良好


🤖 由 AI 代码审查机器人自动生成 | 2026-08-18 04:57:50 | 模型:

### 【阻塞级判定】 - 是否存在阻塞级问题:是 - 阻塞级问题数量:2 个 ### 📊 审查概览 - 整体评价:需修改 - 建议级问题数量:0 个 ### 🔴 阻塞级问题(必须修复) 1. **[apps/web/src/api/auth/tokenRefresh.ts: 39-77] 用户登出时存在竞态条件导致重新登录** - 问题类型:逻辑bug / 安全漏洞 - 问题描述:`cancelProactiveRefresh` 函数仅清除了定时器,但没有取消正在进行的 `executeTokenRefresh` 操作。如果用户在 Token 刷新请求进行中(`activeRefreshPromise` pending)点击登出,虽然 `clearAuth` 会清空 Store,但刷新请求仍在后台运行。一旦刷新请求成功返回,`executeTokenRefresh` 中的 `setAuth` 会被执行,导致用户被重新“自动登录”,绕过了用户的登出意图。 - 修改建议:引入一个取消标志(如 `isRefreshCancelled`)。在 `cancelProactiveRefresh` 中将该标志设为 `true`。在 `executeTokenRefresh` 的 `try` 块中,调用 `setAuth` 之前检查该标志,如果已取消则跳过更新状态。 2. **[apps/web/src/api/client.ts: 110] 刷新失败后的重定向路径不一致** - 问题类型:逻辑bug - 问题描述:当 `executeTokenRefresh` 返回 `null`(即无 user 或 refreshToken)时,代码将页面重定向到 `"/"`(首页)。而在 `tokenRefresh.ts` 的 `executeTokenRefresh` 内部 catch 块中,刷新失败是重定向到 `"/login"`。这种不一致可能导致在 401 错误场景下,用户被错误地导向首页(可能再次触发 401 循环或显示访客视图),而不是统一的登录页。 - 修改建议:将 `window.location.href = "/"` 修改为 `window.location.href = "/login"`,保持认证失败行为的一致性。 ### 💡 改进建议(不阻塞合并) 无 ### ✅ 良好实践 - 引入 `activeRefreshPromise` 锁机制有效解决了并发刷新导致的 Token 覆盖问题。 - 测试用例更新及时,覆盖了新的刷新逻辑路径。 --- ✅ 格式检查通过 | ❌ 逻辑审查需修改 | ✅ 性能良好 --- <sub>🤖 由 AI 代码审查机器人自动生成 | 2026-08-18 04:57:50 | 模型: </sub> <!-- AI_CODE_REVIEW_AUTO_COMMENT -->
auto-approve-bot approved these changes 2026-08-18 12:58:48 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
auto-approve-bot approved these changes 2026-08-18 12:58:48 +08:00
auto-approve-bot left a comment
Collaborator

CI全绿,自动审批通过。

CI全绿,自动审批通过。
xiaoxia merged commit 82e05fcdbb into develop 2026-08-18 13:42:32 +08:00

🗑️ 预览环境已清理

PR #1416 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1416 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.