羽球搭子 HarmonyOS 实战(19):账号认证后的数据作用域
一、登录成功之后真正困难的是“不串数据”球友甲登录后创建了一场周末对局退出账号再让球友乙登录同一台设备。如果页面仍然显示甲的对局、邀请码或个人胜率认证虽然成功数据边界却已经失效。账号系统不能只回答“当前有没有 token”还要回答“当前所有持久化数据属于谁”。羽球搭子的处理方式是把认证会话和业务数据分开保存。认证存储负责 token、过期时间和用户资料对局存储、云端会话状态再读取稳定的用户 ID生成各自的持久化键。昵称不会参与新的作用域计算因为昵称允许修改也可能重名。这样登录、退出和切换账号时应用可以清空内存镜像再从新作用域恢复数据。这套边界解决的是本机多账号隔离不等同于服务端权限。服务端仍然必须根据令牌校验资源归属客户端作用域负责避免旧账号数据在界面上短暂泄漏并保证离线缓存不会互相覆盖。二、认证会话只保存身份不直接承载业务对象认证存储中只需要三类值访问令牌、绝对过期时间和用户资料。登录接口通常返回相对秒数保存时立即换算成绝对时间后续每次取 token 都做过期判断。令牌为空或已经过期时业务层统一得到空字符串不需要每个页面重复比较时间。export class AuthSessionStore { static readonly TOKEN cloud_auth_token static readonly EXPIRES_AT cloud_auth_expires_at static readonly USER cloud_auth_user static save(session: AuthSession): void { const expiresAt Date.now() session.expiresIn * 1000 AppStorage.setOrCreatestring(this.TOKEN, session.token) AppStorage.setOrCreatenumber(this.EXPIRES_AT, expiresAt) AppStorage.setOrCreateUserProfile(this.USER, session.user) this.persist(session.token, expiresAt, session.user) } static getToken(): string { const token AppStorage.getstring(this.TOKEN) ?? const expiresAt AppStorage.getnumber(this.EXPIRES_AT) ?? 0 return token.length 0 expiresAt Date.now() ? token : } }这里有一个刻意的取舍运行期 AppStorage 更新成功后即使 Preferences 刷盘失败当前页面仍可继续使用但下次冷启动可能需要重新登录。认证存储不应该在持久化异常时伪装成完整成功因此界面可以在关键操作前再次检查getToken()服务端请求也必须允许返回未授权错误。数据适合的存储位置原因失效动作token认证存储请求鉴权需要生命周期独立过期或退出时删除expiresAt认证存储避免使用过期 token每次读取时比较userId、昵称、头像认证存储页面展示及作用域选择用户资料更新时覆盖对局摘要与详情对局存储需要离线使用和重启恢复按 userId 分区云端版本、邀请码、别名云会话存储用于同步和冲突判断按 userId 分区三、稳定 userId 进入键空间业务存储不把所有账号的数据写入同一个sessions键而是先计算作用域。已登录用户使用服务端返回的稳定 ID未登录状态保留默认键继续支持本地离线使用。这样两个账号的同名对局也不会相互覆盖。function currentScope(): string { const user AuthSessionStore.getUser() if (user ! undefined user.id.length 0) { return u_${user.id}_ } return } function scopedKey(baseKey: string): string { const scope currentScope() return scope.length 0 ? baseKey : ${scope}${baseKey} } function detailKey(sessionId: string): string { return scopedKey(session_${sessionId}) }作用域前缀不是加密也不是权限控制。它只是明确“哪一份本地缓存属于哪位用户”。如果攻击者能够直接读取应用沙箱仍需要系统沙箱、设备锁和敏感数据保护提供安全边界。服务端接口更不能信任客户端拼出的 userId而应从令牌解析身份。四、从旧键迁移到新作用域要可重复应用早期可能只有一个无作用域键或者曾经用昵称哈希区分用户。升级后直接只读新键会让用户误以为历史对局丢失。恢复逻辑因此按“新作用域 → 无作用域旧键 → 昵称旧键”的顺序查找找到旧数据后写入新键但不在读到第一份数据前删除旧值。function readSessions(prefs: Preferences): string { const primary prefs.getSync(scopedKey(g_sessions), ) as string if (primary.length 0) { return primary } const unscoped currentScope().length 0 ? prefs.getSync(g_sessions, ) as string : if (unscoped.length 0) { prefs.putSync(scopedKey(g_sessions), unscoped) return unscoped } const legacy prefs.getSync(legacyScopedKey(g_sessions), ) as string if (legacy.length 0) { prefs.putSync(scopedKey(g_sessions), legacy) } return legacy }迁移必须具备幂等性第一次启动完成复制第二次启动首先命中新键不再产生不同结果。旧数据是否删除应由独立的版本迁移策略决定不能夹在页面加载中立即清理否则一次解析异常就可能同时破坏新旧两份数据。五、切换账号时先清镜像再恢复目标作用域退出账号的关键动作不是把按钮文字改成“未登录”而是让依赖账号的内存状态立即失效。对局摘要、当前场次、云端会话版本和统计结果都可能仍在 AppStorage 中。正确顺序是清除认证会话重置账号模式重新恢复账号作用域存储最后刷新页面派生状态。function switchAccount(next: AuthSession | undefined): void { if (next undefined) { AuthSessionStore.clear() } else { AuthSessionStore.save(next) } SessionStore.clearRuntimeMirror() CloudSessionStateStore.clearRuntimeMirror() CloudSessionStateStore.hydrateFromPrefs() SessionStore.hydrateFromPrefs() StatsViewModel.reload() }这里“先清再读”非常重要。如果直接覆盖少数字段目标账号没有某项数据时上一账号的旧值可能继续留在页面。清理动作只针对运行期镜像不应粗暴清空整个 Preferences 文件否则退出账号会连带删除其他账号的离线数据。六、页面只消费可观察结果页面不需要知道作用域键的具体格式。它只订阅登录态、当前用户名、对局列表和统计模型并通过统一方法触发重新装载。认证成功、退出和用户资料更新都走同一条刷新路径避免“首页已经切换统计页还是旧账号”的局部更新。class AccountViewModel { Trace signedIn: boolean false Trace userName: string Trace sessions: SessionSummary[] [] reload(): void { const user AuthSessionStore.getUser() this.signedIn AuthSessionStore.getToken().length 0 this.userName this.signedIn ? user?.nickname ?? : this.sessions SessionStore.list() } signOut(): void { AuthRepository.signOut() AccountScopedStores.reload() this.reload() } }页面层保留加载态和错误态但不自行拼接持久化键。只要作用域逻辑集中在 Store 内部将来调整键格式或增加迁移版本时就不需要逐页修改。七、五条失败路径决定隔离是否可靠场景容易出现的错误防护策略可见结果token 已过期页面仍显示已连接读取 token 时统一校验绝对时间回到未登录态账号 A 退出、B 登录A 的 AppStorage 残留先清运行期镜像再恢复 BB 只看到自己的数据用户修改昵称本地作用域变化新作用域只使用稳定 userId数据保持不变旧版本无作用域数据升级后历史为空按顺序读取并迁移旧键首次启动完成兼容Preferences 数据损坏JSON 解析中断捕获异常并使用空模型页面可继续进入还要警惕“退出即删除全部本地数据”的过度清理。多数情况下退出只是断开云端身份用户再次登录仍希望恢复自己的离线对局。真正的本地清除应该是独立、明确、带确认的设置操作。八、怎样验证没有串号验收至少准备两个测试账号和一份未登录数据。账号 A 创建对局并设为当前场次退出后确认页面先变为空账号 B 登录创建不同名称的对局再次切回 AA 的列表和当前场次应恢复。随后修改 A 的昵称确认数据仍归属于同一 userId。冷启动验证同样必要分别在 A、B 登录状态下结束进程并重启确认认证过期判断、作用域恢复和页面刷新顺序一致。再构造一个已经过期的绝对时间应用应拒绝返回 token而不是等服务端第一次报错才改变界面。Preferences 的具体能力和约束应以 HarmonyOS ArkData Preferences 官方指南 为准。账号隔离设计还应结合目标 SDK 的数据保护要求和服务端鉴权策略复核。九、总结账号认证后的数据作用域是一条完整链路认证会话提供稳定 userId业务 Store 用它生成键空间账号切换先清运行期镜像再从目标作用域恢复页面只消费恢复后的可观察状态。昵称、头像和页面文案都不能代替稳定身份。这套实现让本地离线与云端账号可以共存未登录用户继续使用默认分区登录用户拥有独立缓存旧版本数据通过幂等迁移进入新键。它不能替代服务端权限控制却能把同机多账号最常见的串数据问题挡在 UI 出现之前。

相关新闻

为什么83%的AI工作流项目6个月内失败?——头部SaaS团队不愿公开的5个致命盲区

为什么83%的AI工作流项目6个月内失败?——头部SaaS团队不愿公开的5个致命盲区

更多请点击: https://codechina.net 第一章:AI自动化工作流失败的底层归因与认知重构 AI自动化工作流的频繁中断并非源于模型能力不足,而常根植于对“自动化”本质的误读——将流程编排等同于智能决策,忽视了数据契约、状态一致性…

2026/7/24 1:04:19阅读更多 →
职场人效率跃迁手册(2024最新版):用AI重构文档/会议/审批流,实测周效提升3.7倍

职场人效率跃迁手册(2024最新版):用AI重构文档/会议/审批流,实测周效提升3.7倍

更多请点击: https://intelliparadigm.com 第一章:AI办公效率跃迁的认知革命与底层逻辑 传统办公范式正经历一场静默却深刻的重构——其驱动力并非单纯工具迭代,而是人类对“智能协同”本质理解的根本性转变。当大语言模型不再仅作为问答机器…

2026/7/24 1:04:19阅读更多 →
【RT-DETR涨点改进】CCF-A 2026顶刊 | 独家注意力改进篇|引入RSWAttention​​​​​​​重构滑动窗口注意力模块,聚焦细粒度局部特征,含10种创新改进点,助力目标检测高效涨点

【RT-DETR涨点改进】CCF-A 2026顶刊 | 独家注意力改进篇|引入RSWAttention​​​​​​​重构滑动窗口注意力模块,聚焦细粒度局部特征,含10种创新改进点,助力目标检测高效涨点

一、本文介绍 🔥本文给大家介绍使用 RSWAttention重构滑动窗口注意力模块 改进RT-DETR网络模型,其核心作用在于通过局部滑动窗口与全局MLP(GMLP)的结合,强制模型在聚焦细粒度局部特征的同时弥补全局上下文依赖的建模 。这一改进的显著优势在于:它能有效过滤传统全局注意…

2026/7/24 1:04:19阅读更多 →
Qwen-VL多模态大模型:部署、微调与应用实践

Qwen-VL多模态大模型:部署、微调与应用实践

1. Qwen-VL模型概述Qwen-VL(通义千问视觉语言大模型)是阿里巴巴云推出的多模态大模型系列,基于Qwen(通义千问)语言大模型扩展而来。这个系列模型能够同时处理图像、文本和边界框输入,输出文本和边界框标注&…

2026/7/24 2:24:32阅读更多 →
AI降重工具横评:千笔与SpeedAI对比分析

AI降重工具横评:千笔与SpeedAI对比分析

1. 项目概述:AI内容检测工具横评背景在内容创作领域,AI生成内容的泛滥已经成为一个不可忽视的现象。根据我过去半年对30多个内容平台的跟踪观察,超过60%的机构开始部署AI检测机制,这对创作者尤其是学生群体造成了实质性的影响。最…

2026/7/24 2:24:32阅读更多 →
AI专著生成工具:核心功能与选型指南

AI专著生成工具:核心功能与选型指南

1. AI专著生成工具的核心价值解析在学术研究领域,专著撰写一直是衡量学者专业深度和学术影响力的重要指标。传统专著创作往往需要耗费研究者数月甚至数年的时间,从文献收集、框架搭建到内容撰写和反复修改,每个环节都充满挑战。特别是在当前学…

2026/7/24 2:24:32阅读更多 →
支付业务-预付卡

支付业务-预付卡

预付卡(也称储值卡)是一种预先充值、先付费后消费的支付工具,其核心特点和运作机制如下:一、核心定义与特点​​预付性质​​持卡人需在消费前将资金存入卡内(如充值、购买),消费时直接从卡内余…

2026/7/24 2:24:32阅读更多 →
bash信号处理与trap命令:编写健壮的脚本

bash信号处理与trap命令:编写健壮的脚本

信号概述与脚本中捕获的必要性 在Linux系统中,信号是一种进程间异步通信机制。当用户按下Ctrl+C、系统关机或进程异常终止时,内核会向相关进程发送信号。对于长时间运行的脚本,若未正确处理信号,可能导致临时文件残留、资源泄漏等问题。通过bash内置的trap命令,我们可以捕…

2026/7/24 2:24:32阅读更多 →
基于YOLO与DeepSeek的智能无人机检测系统开发实践

基于YOLO与DeepSeek的智能无人机检测系统开发实践

1. 项目概述这个基于深度学习的无人机识别检测系统整合了当前最前沿的计算机视觉技术和现代化Web开发框架,构建了一个功能完善、性能优异的无人机检测平台。系统核心采用YOLOv8至v12系列目标检测算法,结合DeepSeek大语言模型的智能分析能力,实…

2026/7/24 2:22:32阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/24 0:58:53阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 0:58:53阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 0:58:53阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好,我是一名编程初学者,同时这也是我编程学习之路上的第一篇博客。在这里,我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手,目前在学习c语言,我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:06阅读更多 →
【LeetCode 54】螺旋矩阵

【LeetCode 54】螺旋矩阵

问题描述: 解法: 1、模拟(参考自【LeetCode 54】螺旋矩阵-CSDN博客) int *spiralOrder(int **matrix, int matrixSize, int *matrixColSize, int *returnSize) {static const int dirs[4][2] {{0, 1}, {1, 0}, {0, -1}, {-1, …

2026/7/24 0:00:06阅读更多 →
2026 WAIC:模型隐身、智能体疯野,厂商竞赛聚焦办公场景与商业闭环

2026 WAIC:模型隐身、智能体疯野,厂商竞赛聚焦办公场景与商业闭环

知春路不相信模型领先今年WAIC大会,昔日AI六小龙来了五家,分别是Kimi、阶跃星辰、Minimax、百川智能、零一万物。连放弃基模的百川和零一万物都来了,唯一缺席的竟是近几个月来风光无限的智谱。(DeepSeek一直不参加)WAI…

2026/7/24 0:00:06阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/23 22:58:43阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/23 18:58:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/23 18:58:18阅读更多 →