4.2 KiB
4.2 KiB
用户端令牌失效恢复操作日志
操作时间:2026-09-04
操作类型:修改、扩展
影响模块:用户端 Flutter App 请求层、会话管理、鉴权路由及错误展示
操作前状态
浏览器残留的用户令牌失效后,首页、订单和个人中心的受保护接口返回 401,但请求层将其转换为普通网络错误。内存和浏览器安全存储中的令牌仍被视为有效,路由因此把 /login 再次重定向到 /home,用户无法自行恢复登录。
具体操作
- 在统一请求层识别受保护请求的 HTTP 401,以及业务码
1301—1314、1715,抛出专用会话失效异常。 - 请求层把实际被拒绝的令牌交给会话层;会话层仅在该令牌仍为当前令牌时执行失效,防止迟到旧请求清除新会话。
- 会话失效立即清空内存令牌并通知根路由,持久化令牌采用幂等、尽力而为的异步清理;新登录写入前等待旧清理结束。
- 鉴权守卫通过
/login?redirect=...&reason=expired保存原目标页,并严格限制为站内绝对路径。 - 登录成功后使用替换导航返回原目标页;目标缺失或非法时回到首页。
- 注册流程继续携带原目标页;写操作鉴权失败后只返回原页面,不自动重放。
- 首页、商城、订单、个人中心和通用记录列表忽略专用会话失效异常,避免重复显示网络错误。
操作后状态
失效令牌首次被服务端拒绝后,用户会自动进入登录页并看到“登录状态已失效,请重新登录”。重新登录后返回登录前目标页;多个并发 401 只清理和通知一次。普通断网、超时、服务端错误及未鉴权登录接口失败仍按原逻辑展示,不会误清理会话。
代码变更
apps/user_app/lib/data/services/api_client.dart(+66/-5):统一鉴权失败识别、旧令牌回调和专用异常。apps/user_app/lib/app/dependencies.dart(+47/-8):幂等会话失效、存储清理及新旧令牌竞态保护。apps/user_app/lib/app/auth_navigation.dart(新增 33 行):新增站内目标页校验和鉴权地址构造。apps/user_app/lib/app/router.dart(+28/-6):保存目标页、失效原因及登录后安全回跳。apps/user_app/lib/ui/features/auth/login_page.dart(+24/-2):显示会话失效提示并把目标页传入注册流程。apps/user_app/lib/ui/features/auth/register_page.dart(+26/-2):注册完成后保留原登录目标页。- 首页、个人中心、商城、订单和通用记录列表(合计 +38/-7):抑制重复鉴权错误。
apps/user_app/test/app/(新增 205 行)、apps/user_app/test/data/api_client_test.dart(+97/-2):新增会话、路由、安全跳转和请求层回归测试。docs/03-用户端App需求.md、docs/11-数据接口与安全.md(各新增 2 行):同步功能与安全约束。
验证结果
flutter analyze --no-pub:通过,无问题。flutter test --no-pub:通过,共 27 项测试。flutter build web --release --no-pub --dart-define=API_BASE_URL=http://rest.heqiapp.com:通过。- 本地用户端已使用
API_BASE_URL=http://127.0.0.1:12426重新生成 Release Web 构建,并由隐藏运行的 Python 静态服务在5180提供访问;已停止 Flutter 调试服务,不再依赖 DDC 调试模块和随机 WebSocket。localhost、127.0.0.1均返回 HTTP 200,裸根地址可自动跳转并实际渲染带失效提示的登录页。 - 已覆盖 HTTP 401、HTTP 200 鉴权业务码、二进制头像接口、未鉴权接口不清理会话、并发失效、迟到旧请求、存储删除失败、开放重定向防护和登录后回跳。
风险评估
- 会话失效依据请求实际携带的令牌比对当前令牌,降低并发和重新登录过程中的竞态风险。
- 持久化删除失败时可能在应用下次完全启动后再次恢复旧令牌,但当前运行会立即退出错误状态;后续受保护请求仍会重新触发清理,不会永久困住用户。
redirect只允许站内绝对路径并排除鉴权页,避免开放重定向和登录循环。- 任何产生副作用的业务请求均不自动重放,避免重复支付、下单、退款或工单。