Account Kit 已撤权,旧会话为什么还能访问:HarmonyOS 7 token 失效与单飞刷新怎么守
用户退出账号后,后台队列里的一次请求仍然成功;另一次请求同时刷新 token,又把页面带回登录态。问题不在“有没有清空一个字符串”,而在于会话代际、撤权结果和并发刷新没有统一所有者。面向 HarmonyOS 7 的账号链路,退出必须让旧一代所有提交失效,刷新也只能有一个进行中的任务。
验证范围:官方页面用于核对 HarmonyOS 7/API 26 的能力方向与开发边界;文中代码只验证应用侧状态机、预算或一致性模型。当前电脑是 API 24 SDK,且没有连接 HarmonyOS 7 真机,所以下面的断言不等同于 API 26 编译、真机性能或上架审核结果。
用退出与并发请求重现旧会话
发起两个需要身份的请求,其中一个延迟;立即退出账号,同时让另一个请求触发刷新。记录 sessionGeneration、refreshOwner 和响应提交结果。退出后任何旧 generation 的成功响应都不能更新页面或缓存。
案例一:前台查询在退出后迟到
网络层可以收到响应,但提交层发现 generation 已变化,应丢弃结果并清理该账号缓存,而不是把页面重新显示为已登录。
案例二:多个接口同时遇到过期
第一个请求成为刷新所有者,其余等待同一结果。刷新期间如果用户退出,刷新结果也必须因 generation 过期而作废。
过期、撤权和退出不是同一状态
token 过期意味着可以尝试刷新,撤权意味着服务端不再接受,主动退出则要求本地立即终止整个会话。把三者都处理成“再刷新一次”会让旧身份复活。
classSessionGate{generation=0;refreshing=false;logout(){this.generation++;this.refreshing=false;}capture(){returnthis.generation;}accept(g:number){returng===this.generation;}}constgate=newSessionGate();constold=gate.capture();gate.logout();if(gate.accept(old))thrownewError('退出后的旧会话仍可提交');这段模型用确定输入验证“退出后所有旧代际请求和刷新结果都不能提交”。它适合先发现应用侧边界错误,但不会冒充平台接口或设备性能测试。
刷新策略如何取舍
| 方案 | 适用范围 | 主要风险 |
|---|---|---|
| 只清 token 字符串 | 无并发请求 | 旧响应仍会写回 |
| 每个请求各自刷新 | 低并发原型 | 刷新风暴与竞态 |
| 会话代际加单飞刷新 | 正式账号系统 | 需要统一网络层 |
账号仓库持有 sessionGeneration 和唯一刷新任务。退出先换代,再清凭证和缓存;任何异步结果提交前都核对 generation。
用会话代际关闭旧世界
封装AuthenticatedRequestScope,自动附带会话代际、等待单飞刷新并处理撤权终态。业务页面不直接保存 token,也不自行重试身份错误。
安全验收不能只看页面跳转
- 退出后迟到成功响应不更新 UI。
- 多个 401 只触发一次刷新。
- 撤权不会进入无限刷新循环。
- 账号 A 的缓存不会写入账号 B。
- 日志不打印 token 原文。
账号安全的边界在异步提交点,不在退出按钮的动画。让会话换代成为硬门禁,旧身份才会真正结束。
官方资料
- HarmonyOS 7 新能力
- HarmonyOS 应用开发指南
- 2026 年 9 月开发者月刊