【OpenHarmony/HarmonyOs 】50|hilog日志脱敏:用户标识、消息内容与异常对象的安全输出 🔐

本文基于当前项目 EntryAbility.etsEntryBackupAbility.etsLoginPage.etsCloudDBService.etsChatPage.etsChatDetailPage.ets 的真实日志代码展开。
项目已经使用 hilog 记录启动、登录和 Cloud DB 状态,但仍存在直接拼接 UID、公开输出完整异常、混用 console 与 hilog 等问题;本文给出适合 HarmonyOS NEXT 项目的分级、脱敏与审计方案。

一、为什么“只在本地打印”也需要脱敏?

移动应用日志可能出现在:

  • 开发机调试窗口;
  • 测试人员的问题附件;
  • 自动化测试产物;
  • 崩溃分析平台;
  • 用户主动导出的诊断包;
  • 团队共享的截图和文章。

日志一旦离开变量所在进程,就进入了新的数据流转链路。

因此日志安全不能依赖“我不会把它发出去”这种假设。


二、项目当前有哪些真实风险点?

登录成功后直接拼接用户 UID:

hilog.info(0x0000, 'AGC', 'Login Success: ' + user.getUid());

登录失败时序列化完整异常:

hilog.error(0x0000, 'AGC', 'Login Failed: ' + JSON.stringify(e));

Cloud DB 初始化失败也输出整个对象:

hilog.error(0x0000, 'CloudDBService',
  'Cloud DB Initialization failed: ' + JSON.stringify(err));

这些写法调试方便,但异常对象可能包含服务地址、请求参数、账号标识或 SDK 内部上下文。


三、%{public}s 的含义必须认真对待

项目启动日志中存在:

hilog.error(DOMAIN, 'AGC',
  'AGC Init Failed: %{public}s', JSON.stringify(err));

public 表示该字段可以明文显示。

它适合固定状态、公开错误码、非敏感模块名,不适合未经审查的完整异常对象。

敏感字段应避免输出;确需诊断时,也应先转换为安全摘要,再决定公开属性。


四、先定义日志数据分类

1. 可以直接记录

  • 生命周期阶段;
  • 模块名称;
  • 固定操作名称;
  • 公开错误码;
  • 重试次数;
  • 耗时;
  • 结果数量。

2. 必须脱敏后记录

  • UID;
  • 会话 ID;
  • 消息 ID;
  • 手机号;
  • 邮箱;
  • 文件名;
  • 搜索关键词。

3. 原则上禁止记录

  • token;
  • 密码;
  • 验证码;
  • 聊天正文;
  • 私密日记正文;
  • 精确位置;
  • 联系人详情;
  • 完整请求头;
  • 签名密钥。

五、日志应该记录事件,而不是复制业务对象

不推荐:

hilog.info(DOMAIN, TAG, '%{public}s', JSON.stringify(user));

推荐:

hilog.info(DOMAIN, TAG,
  'event=login_success provider=%{public}s user=%{public}s',
  providerName, maskedUid);

结构化事件让日志更容易检索,也减少“为了方便把整个对象打出来”的冲动。


六、常用脱敏规则

UID

保留首尾少量字符:

1234567890abcdef1234****cdef

手机号

13812345678 138****5678

邮箱

alice@example.com → a***e@example.com

会话与消息 ID

可以记录不可逆摘要、短追踪码或首尾片段,但不能借日志重新关联完整个人轨迹。

内容类字段

不要记录正文,可记录长度、类型和是否为空:

message_type=text content_length=32

七、一个安全日志门面的设计方向

推荐统一封装:

import { hilog } from '@kit.PerformanceAnalysisKit';

export class AppLogger {
  static info(tag: string, event: string): void {
    hilog.info(0x0000, tag, 'event=%{public}s', event);
  }

  static error(tag: string, event: string, code: string): void {
    hilog.error(0x0000, tag,
      'event=%{public}s code=%{public}s', event, code);
  }
}

真实项目还可以增加耗时、追踪 ID、构建环境与采样策略。

门面的核心价值是把安全规则放在统一边界,而不是要求每个页面作者临场判断。


八、异常对象不能直接 JSON.stringify

JSON.stringify(error) 常出现三个问题:

  1. 标准 Error 的关键字段可能不可枚举,最终只得到 {}
  2. SDK 异常可能带有大量内部字段;
  3. 未知对象可能包含敏感请求上下文。

推荐提取允许名单:

  • 统一错误码;
  • 安全分类;
  • 是否可重试;
  • 操作名称;
  • 内部追踪 ID。

错误 message 只有经过审查后才能进入日志。


九、日志级别如何划分?

debug

只用于开发期流程细节,不应依赖它完成生产诊断。

info

记录关键业务阶段成功,例如初始化完成、订阅建立、页面加载完成。

warn

记录可恢复降级,例如 Zone 暂不可用、使用 Mock 数据、即将重试。

error

记录操作失败,但只输出安全错误摘要。

fatal 级别应只用于导致核心进程或关键能力不可继续的情况。


十、固定 DOMAIN 与 TAG

当前项目普遍使用 0x0000,标签包括 AGCCloudDBCloudDBServicetestTag

建议:

  • DOMAIN 使用团队统一分配值;
  • TAG 表示稳定模块,而不是临时调试名称;
  • 事件名表示具体动作;
  • 不把用户输入放进 TAG;
  • 不使用 testTag 承载生产关键日志。

十一、逐项日志安全核验

检查项 1:登录成功

  • 检查目标:只记录登录方式和脱敏用户标识。
  • 常见反例:直接拼接 user.getUid()。
  • 推荐动作:使用掩码 UID 或短追踪标识。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 2:登录失败

  • 检查目标:记录统一错误码与阶段。
  • 常见反例:JSON.stringify 完整异常。
  • 推荐动作:先映射为安全错误摘要。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 3:游客登录

  • 检查目标:记录模式切换而非设备信息。
  • 常见反例:输出完整上下文对象。
  • 推荐动作:仅记录 event=guest_login。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 4:用户同步

  • 检查目标:记录新增或已存在的结果。
  • 常见反例:输出用户对象和头像地址。
  • 推荐动作:只记录 operation 与 result。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 5:Cloud DB 初始化

  • 检查目标:记录 Zone 名称是否成功。
  • 常见反例:异常对象全部公开。
  • 推荐动作:记录标准错误码与可重试性。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 6:Zone 不可用

  • 检查目标:使用 warn 表达降级。
  • 常见反例:悄悄吞掉异常或打印敏感配置。
  • 推荐动作:记录 fallback_used=true。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 7:查询用户

  • 检查目标:记录返回数量与耗时。
  • 常见反例:记录每个用户 UID、昵称和手机号。
  • 推荐动作:只输出 count 与 duration。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 8:好友搜索

  • 检查目标:记录搜索模式与结果数量。
  • 常见反例:记录原始搜索关键词。
  • 推荐动作:记录 keyword_length 与 mode。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 9:聊天订阅

  • 检查目标:记录建立、断开与重连。
  • 常见反例:输出整个 snapshot。
  • 推荐动作:记录 conversation_ref 与 count。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 10:发送消息

  • 检查目标:记录类型、长度和结果。
  • 常见反例:记录聊天正文。
  • 推荐动作:输出 content_length 与 msg_type。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 11:接收消息

  • 检查目标:记录批次数量。
  • 常见反例:遍历打印每条内容。
  • 推荐动作:使用 aggregate_count。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 12:消息失败

  • 检查目标:记录写入阶段与安全码。
  • 常见反例:输出发送者、接收者和正文。
  • 推荐动作:使用 request_trace_id。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 13:附件消息

  • 检查目标:记录附件类别和大小。
  • 常见反例:输出本地绝对路径。
  • 推荐动作:文件名脱敏且不记录路径。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 14:位置消息

  • 检查目标:只记录类型。
  • 常见反例:输出经纬度和地址。
  • 推荐动作:记录 location_permission_state。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 15:联系人消息

  • 检查目标:只记录功能结果。
  • 常见反例:输出姓名和电话。
  • 推荐动作:禁止记录联系人字段。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 16:心情发布

  • 检查目标:记录可见性和内容长度。
  • 常见反例:输出心情正文与标签原文。
  • 推荐动作:标签仅记录数量。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 17:私密日记

  • 检查目标:默认禁止内容日志。
  • 常见反例:为了调试打印私密正文。
  • 推荐动作:只记录 operation_id。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 18:点赞操作

  • 检查目标:记录对象短标识与结果。
  • 常见反例:输出完整动态对象。
  • 推荐动作:记录 target_ref 与 count_delta。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 19:删除操作

  • 检查目标:记录对象类型和结果。
  • 常见反例:输出被删除内容。
  • 推荐动作:记录 target_type 与 status。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 20:路由跳转

  • 检查目标:记录目标页面枚举。
  • 常见反例:输出完整 params。
  • 推荐动作:参数只使用允许名单。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 21:启动能力

  • 检查目标:记录生命周期事件。
  • 常见反例:公开 Want 全对象。
  • 推荐动作:仅记录 launch_reason。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 22:窗口加载

  • 检查目标:记录错误码。
  • 常见反例:公开窗口对象或完整异常。
  • 推荐动作:使用 code 与 stage。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 23:备份恢复

  • 检查目标:记录版本号的允许字段。
  • 常见反例:JSON.stringify BundleVersion 全量。
  • 推荐动作:提取公开版本字段。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 24:鉴权检查

  • 检查目标:记录 authenticated 布尔值。
  • 常见反例:console.error 原始异常。
  • 推荐动作:统一进入安全 logger。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 25:Mock 降级

  • 检查目标:记录 fallback 原因。
  • 常见反例:把 Mock 用户详情全部打印。
  • 推荐动作:记录 fallback_source。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 26:重试

  • 检查目标:记录 attempt 与 delay。
  • 常见反例:每次打印相同完整堆栈。
  • 推荐动作:首尾采样并聚合计数。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 27:超时

  • 检查目标:记录 operation 和 duration。
  • 常见反例:打印请求体。
  • 推荐动作:记录 timeout_ms。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 28:取消请求

  • 检查目标:记录取消原因枚举。
  • 常见反例:把页面状态全部输出。
  • 推荐动作:使用 reason_code。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 29:竞态丢弃

  • 检查目标:记录版本号差异。
  • 常见反例:输出旧响应正文。
  • 推荐动作:只记录 request_version。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 30:空状态

  • 检查目标:通常不需要 error 日志。
  • 常见反例:无数据当异常打印。
  • 推荐动作:用指标区分 empty 与 error。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 31:权限拒绝

  • 检查目标:记录权限名称和结果。
  • 常见反例:记录用户精确位置。
  • 推荐动作:只记录 permission 与 granted。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 32:相机失败

  • 检查目标:记录能力错误码。
  • 常见反例:输出图片 URI。
  • 推荐动作:路径和 URI 一律脱敏。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 33:相册失败

  • 检查目标:记录选择阶段。
  • 常见反例:打印返回资源列表。
  • 推荐动作:记录 selected_count。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 34:网络状态

  • 检查目标:记录连接类型粗粒度状态。
  • 常见反例:输出 IP、SSID 或设备标识。
  • 推荐动作:避免网络身份信息。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 35:HTTP 请求

  • 检查目标:记录接口代号与状态码。
  • 常见反例:输出 URL 查询参数和 Header。
  • 推荐动作:接口使用内部 action 名。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 36:Token 刷新

  • 检查目标:记录成功与失败。
  • 常见反例:输出 token 内容。
  • 推荐动作:任何级别禁止 token。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 37:验证码

  • 检查目标:记录发送结果。
  • 常见反例:输出验证码。
  • 推荐动作:仅记录 channel 与 result。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 38:手机号

  • 检查目标:默认不输出。
  • 常见反例:完整手机号进入日志。
  • 推荐动作:必要时使用 3+4 掩码。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 39:邮箱

  • 检查目标:默认不输出。
  • 常见反例:完整邮箱进入日志。
  • 推荐动作:必要时局部掩码。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 40:昵称

  • 检查目标:谨慎视为个人信息。
  • 常见反例:直接记录昵称和搜索词。
  • 推荐动作:用内部短标识替代。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 41:头像

  • 检查目标:不记录完整 URL。
  • 常见反例:URL 可能携带签名参数。
  • 推荐动作:仅记录 avatar_present。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 42:UID

  • 检查目标:统一掩码策略。
  • 常见反例:不同页面各自 substring。
  • 推荐动作:集中实现 maskIdentifier。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 43:会话 ID

  • 检查目标:使用不可逆短摘要。
  • 常见反例:原值贯穿多条日志。
  • 推荐动作:避免跨场景追踪用户。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 44:消息 ID

  • 检查目标:仅用于短期排障。
  • 常见反例:永久明文保留。
  • 推荐动作:设置短追踪 ID 与保留期。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 45:设备 ID

  • 检查目标:原则上禁止。
  • 常见反例:作为“方便排查”长期输出。
  • 推荐动作:使用临时会话追踪 ID。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 46:应用版本

  • 检查目标:可公开记录。
  • 常见反例:与用户信息拼成单一字符串。
  • 推荐动作:使用独立结构字段。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 47:语言设置

  • 检查目标:可记录语言代码。
  • 常见反例:记录用户输入文案。
  • 推荐动作:只输出 locale。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 48:颜色模式

  • 检查目标:可记录 light/dark。
  • 常见反例:输出完整 Configuration。
  • 推荐动作:提取 color_mode。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 49:构建环境

  • 检查目标:可记录 debug/release。
  • 常见反例:输出签名配置。
  • 推荐动作:严禁证书路径和别名。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 50:异常 message

  • 检查目标:经过允许名单审查。
  • 常见反例:默认认为 message 安全。
  • 推荐动作:优先使用映射后的用户无关描述。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 51:异常 stack

  • 检查目标:仅受控开发环境使用。
  • 常见反例:生产全量上传。
  • 推荐动作:裁剪、采样并限制访问。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 52:SDK 错误

  • 检查目标:记录 code 与模块。
  • 常见反例:序列化 SDK 内部对象。
  • 推荐动作:适配器提取安全字段。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 53:未知错误

  • 检查目标:使用 UNKNOWN 分类。
  • 常见反例:把 unknown 强制转字符串。
  • 推荐动作:保留追踪 ID供内部关联。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 54:console 混用

  • 检查目标:统一 hilog 门面。
  • 常见反例:部分页面 console.error。
  • 推荐动作:迁移到一致等级与格式。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 55:字符串拼接

  • 检查目标:使用格式化占位符。
  • 常见反例:敏感值混入固定文案。
  • 推荐动作:字段逐个决定公开性。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 56:public 占位符

  • 检查目标:只标记已确认安全字段。
  • 常见反例:异常对象直接 public。
  • 推荐动作:先脱敏再 public。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 57:private 占位符

  • 检查目标:仍遵循最小记录原则。
  • 常见反例:认为 private 就可记录密码。
  • 推荐动作:秘密字段完全不进入日志。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 58:日志 TAG

  • 检查目标:使用稳定模块名。
  • 常见反例:TAG 包含 UID 或关键词。
  • 推荐动作:TAG 只用于模块过滤。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 59:DOMAIN

  • 检查目标:使用统一合法域。
  • 常见反例:所有示例长期保留 0x0000。
  • 推荐动作:由项目配置集中管理。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 60:事件命名

  • 检查目标:采用稳定 snake_case。
  • 常见反例:自然语言随意变化。
  • 推荐动作:便于检索和指标聚合。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 61:字段顺序

  • 检查目标:同类事件保持一致。
  • 常见反例:每个调用自定义格式。
  • 推荐动作:建立 event、code、trace 顺序。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 62:追踪 ID

  • 检查目标:随机且不含业务身份。
  • 常见反例:直接使用 UID 当 trace。
  • 推荐动作:每次操作生成短期标识。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 63:采样率

  • 检查目标:高频成功日志按需采样。
  • 常见反例:列表滚动每帧打印。
  • 推荐动作:保留错误与关键状态。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 64:去重

  • 检查目标:重复错误按窗口聚合。
  • 常见反例:弱网时刷屏。
  • 推荐动作:记录 suppressed_count。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 65:频率限制

  • 检查目标:同一事件设置上限。
  • 常见反例:订阅回调无限输出。
  • 推荐动作:使用节流或计数。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 66:保留周期

  • 检查目标:按敏感等级设置。
  • 常见反例:日志长期无限保存。
  • 推荐动作:到期自动删除。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 67:访问控制

  • 检查目标:仅授权人员可查看。
  • 常见反例:日志链接公开共享。
  • 推荐动作:最小权限与审计访问。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 68:导出诊断

  • 检查目标:用户知情并可预览。
  • 常见反例:自动上传全部日志。
  • 推荐动作:二次脱敏后导出。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 69:崩溃上报

  • 检查目标:只包含必要上下文。
  • 常见反例:附带最近聊天正文。
  • 推荐动作:清理 breadcrumbs 敏感字段。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 70:测试日志

  • 检查目标:测试账号也按真实规则处理。
  • 常见反例:测试环境关闭脱敏。
  • 推荐动作:保持环境间策略一致。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 71:单元测试

  • 检查目标:验证掩码边界。
  • 常见反例:只测正常手机号。
  • 推荐动作:覆盖空值、短值和 Unicode。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 72:集成测试

  • 检查目标:扫描禁止关键词。
  • 常见反例:靠人工检查输出。
  • 推荐动作:自动拦截 token、phone 模式。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 73:代码评审

  • 检查目标:新增日志逐字段审查。
  • 常见反例:只看日志等级。
  • 推荐动作:检查必要性、敏感性与保留期。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 74:发布构建

  • 检查目标:降低 debug 细节。
  • 常见反例:release 保留所有开发日志。
  • 推荐动作:使用构建策略裁剪。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 75:文章截图

  • 检查目标:再次人工脱敏。
  • 常见反例:直接贴调试控制台。
  • 推荐动作:遮盖 UID、路径和项目标识。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 76:问题工单

  • 检查目标:只附必要片段。
  • 常见反例:复制整段设备日志。
  • 推荐动作:限定时间窗和事件类型。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 77:安全事件

  • 检查目标:记录操作和结果。
  • 常见反例:记录秘密本身。
  • 推荐动作:可审计但不可复原凭据。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 78:审计日志

  • 检查目标:与调试日志分离。
  • 常见反例:用 info 日志代替审计系统。
  • 推荐动作:独立完整性与保留策略。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 79:用户提示

  • 检查目标:错误文案不暴露内部日志。
  • 常见反例:把 errStr 原样显示 UI。
  • 推荐动作:用户文案与诊断信息分离。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 80:多语言

  • 检查目标:事件码不随语言变化。
  • 常见反例:用中文错误文案做检索键。
  • 推荐动作:日志稳定、UI 本地化。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 81:性能

  • 检查目标:避免大对象序列化。
  • 常见反例:每次异常 JSON.stringify 深层对象。
  • 推荐动作:提取少量字段。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 82:内存

  • 检查目标:日志参数即时且轻量。
  • 常见反例:构建巨大字符串后再判断等级。
  • 推荐动作:门面先决定是否记录。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 83:并发

  • 检查目标:日志事件包含独立 trace。
  • 常见反例:靠全局 UID 区分请求。
  • 推荐动作:使用请求级上下文。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 84:订阅销毁

  • 检查目标:记录 listener_removed。
  • 常见反例:页面销毁仍持续刷日志。
  • 推荐动作:生命周期内解除监听。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 85:成功日志

  • 检查目标:只记录关键里程碑。
  • 常见反例:每个函数入口都 info。
  • 推荐动作:减少噪声提高信噪比。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 86:失败日志

  • 检查目标:只在责任边界记录一次。
  • 常见反例:每层 catch 重复 error。
  • 推荐动作:底层返回错误,上层统一落日志。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 87:降级日志

  • 检查目标:warn 并注明 fallback。
  • 常见反例:降级被当成功无痕处理。
  • 推荐动作:让排障看见真实数据来源。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 88:恢复日志

  • 检查目标:记录 recovered=true。
  • 常见反例:只见失败看不见恢复。
  • 推荐动作:闭合故障时间线。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 89:上线审计

  • 检查目标:扫描 hilog、console 与 stringify。
  • 常见反例:只检查新增文件。
  • 推荐动作:覆盖全项目和依赖封装。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

检查项 90:最终标准

  • 检查目标:日志可诊断但不可重建用户隐私。
  • 常见反例:信息越多越好。
  • 推荐动作:最小必要、结构稳定、访问受控。
  • 证据要求:提供代码位置、样例输出或自动扫描结果。
  • 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。

十二、推荐改造顺序

第一步,检索所有 hilogconsoleJSON.stringify(error) 与字符串拼接。

第二步,建立禁止字段、需脱敏字段和可公开字段清单。

第三步,引入统一日志门面与事件命名规范。

第四步,优先整改登录、鉴权、Cloud DB、聊天与备份日志。

第五步,为掩码函数、错误摘要和敏感模式扫描增加测试。

第六步,在 release 构建和问题导出链路中验证最终输出。


十三、常见反模式速查

反模式 风险 正确方向
登录成功打印 UID 用户身份泄露 掩码或短期追踪 ID
完整序列化异常 SDK 上下文泄露 允许名单摘要
把异常标记 public 明文进入日志 先脱敏再决定公开
console 与 hilog 混用 等级和格式不可治理 统一门面
打印消息正文 私密通信泄露 只记类型和长度
每层 catch 都 error 日志重复且难定位 责任边界记录一次
UI 展示原始 errStr 内部信息暴露给用户 用户文案与诊断分离
release 保留全部 debug 噪声和泄露面扩大 构建级裁剪与采样

十四、总结

hilog 脱敏不是给字符串打几个星号。

它要求项目同时治理:

  1. 哪些事件值得记录;
  2. 哪些字段可以公开;
  3. 哪些字段必须掩码或禁止进入日志;
  4. 谁能访问、保存多久、如何导出;
  5. 如何让页面错误文案与内部诊断彻底分离。

好日志应该让工程师看清故障链路,却不能让任何人从日志中还原用户身份、聊天内容或认证凭据。

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐