分享一张订单截图,为什么把手机号也带出去了:HarmonyOS 7 系统分享的数据最小化设计
先看问题是怎么发生的
分享功能最容易被忽略的不是面板能否拉起,而是应用到底交出了什么。订单页把整张业务对象序列化后再生成分享卡片,手机号、内部编号和本地路径可能一起进入图片或文本。接收方只需要标题、金额和公开链接,发送方却把调试字段也带了出去。
验证边界:本文依据文末华为开发者官方资料整理,并用可执行 TypeScript 状态模型验证应用侧分支。当前本机为 API 24 且未连接 HarmonyOS 7 真机,文中的 API 26 代码属于接入骨架,不声称已完成 API 26 编译、真机性能测试或设备兼容认证。上线前仍需在目标 SDK 和真实设备上补齐接口、异常码、权限与性能证据。
根因和工程边界
系统分享之前应先建立“可分享领域对象”,它不是数据库实体的镜像,而是按场景挑选后的最小副本。图片要在独立画布上重新渲染,文字要经过字段白名单,临时 URI 要有清晰的授权和销毁边界。脱敏不能放在 UI 最后一层临时替换,因为不同入口可能绕过同一段代码。
案例一:订单摘要发给客服
只输出订单号后四位、商品名、支付状态和用户主动填写的说明。手机号、收货地址、数据库主键不进入分享 DTO;日志仅记录 requestId 和字段数量。
案例二:长图分享给社交应用
重新渲染一张不含状态栏通知、调试浮层和本地路径的长图。生成失败时退回纯文本摘要,用户关闭面板后清理临时文件与授权。
可以独立运行的状态模型
typeOrder={id:string;phone:string;address:string;name:string;paid:boolean};typeShareOrder={idTail:string;name:string;status:string};functiontoShare(o:Order):ShareOrder{return{idTail:o.id.slice(-4),name:o.name,status:o.paid?'已支付':'待支付'}}constout=toShare({id:'A1234567',phone:'13800000000',address:'secret',name:'套餐',paid:true});if(JSON.stringify(out).includes('138'))thrownewError('敏感字段泄漏');这个小模型只验证应用侧判断,不替代 HarmonyOS 7 真机和目标 SDK。接入平台接口时,应把调用放在模型确定的边界内,并把真实错误码、日志和用户可见结果补进验收记录。
为什么选择这条方案
白名单 DTO 比黑名单删除更稳,因为新增业务字段默认不会外泄。截图前再遮挡只能处理可见文字,无法覆盖文本记录、URI 元数据和调试日志。将分享副本做成独立纯函数,还能被单元测试和代码审查直接检查。
上线前验证清单
| 验证项 | 通过标准 |
|---|---|
| 新增 phone2 字段:不会自动进入分享对象 | 有可重复步骤、日志或可见结果 |
| 图片生成失败:仍可分享最小文本 | 有可重复步骤、日志或可见结果 |
| 连续分享:临时文件互不覆盖 | 有可重复步骤、日志或可见结果 |
| 面板关闭:临时授权及时释放 | 有可重复步骤、日志或可见结果 |
| 日志抽查:没有手机号与本地路径 | 有可重复步骤、日志或可见结果 |
官方资料与证据边界
- 系统分享详情页开发
- ShareExtensionAbility API 参考
- 2026年9月开发者月刊
可复用结论
先把输入、所有者、生命周期和失败回退写成状态,再接入平台能力。这样出现异常时可以回答“哪一步失败、谁负责释放、用户还能做什么”,而不是靠重复调用掩盖问题。