【OpenHarmony/HarmonyOs 】50|hilog日志脱敏:用户标识、消息内容与异常对象的安全输出
【OpenHarmony/HarmonyOs 】50|hilog日志脱敏:用户标识、消息内容与异常对象的安全输出 🔐
本文基于当前项目
EntryAbility.ets、EntryBackupAbility.ets、LoginPage.ets、CloudDBService.ets、ChatPage.ets与ChatDetailPage.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
保留首尾少量字符:
1234567890abcdef → 1234****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) 常出现三个问题:
- 标准
Error的关键字段可能不可枚举,最终只得到{}; - SDK 异常可能带有大量内部字段;
- 未知对象可能包含敏感请求上下文。
推荐提取允许名单:
- 统一错误码;
- 安全分类;
- 是否可重试;
- 操作名称;
- 内部追踪 ID。
错误 message 只有经过审查后才能进入日志。
九、日志级别如何划分?
debug
只用于开发期流程细节,不应依赖它完成生产诊断。
info
记录关键业务阶段成功,例如初始化完成、订阅建立、页面加载完成。
warn
记录可恢复降级,例如 Zone 暂不可用、使用 Mock 数据、即将重试。
error
记录操作失败,但只输出安全错误摘要。
fatal 级别应只用于导致核心进程或关键能力不可继续的情况。
十、固定 DOMAIN 与 TAG
当前项目普遍使用 0x0000,标签包括 AGC、CloudDB、CloudDBService 与 testTag。
建议:
- 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:最终标准
- 检查目标:日志可诊断但不可重建用户隐私。
- 常见反例:信息越多越好。
- 推荐动作:最小必要、结构稳定、访问受控。
- 证据要求:提供代码位置、样例输出或自动扫描结果。
- 通过标准:日志保留排障价值,同时无法恢复用户秘密或正文。
十二、推荐改造顺序
第一步,检索所有 hilog、console、JSON.stringify(error) 与字符串拼接。
第二步,建立禁止字段、需脱敏字段和可公开字段清单。
第三步,引入统一日志门面与事件命名规范。
第四步,优先整改登录、鉴权、Cloud DB、聊天与备份日志。
第五步,为掩码函数、错误摘要和敏感模式扫描增加测试。
第六步,在 release 构建和问题导出链路中验证最终输出。
十三、常见反模式速查
| 反模式 | 风险 | 正确方向 |
|---|---|---|
| 登录成功打印 UID | 用户身份泄露 | 掩码或短期追踪 ID |
| 完整序列化异常 | SDK 上下文泄露 | 允许名单摘要 |
| 把异常标记 public | 明文进入日志 | 先脱敏再决定公开 |
| console 与 hilog 混用 | 等级和格式不可治理 | 统一门面 |
| 打印消息正文 | 私密通信泄露 | 只记类型和长度 |
| 每层 catch 都 error | 日志重复且难定位 | 责任边界记录一次 |
| UI 展示原始 errStr | 内部信息暴露给用户 | 用户文案与诊断分离 |
| release 保留全部 debug | 噪声和泄露面扩大 | 构建级裁剪与采样 |
十四、总结
hilog 脱敏不是给字符串打几个星号。
它要求项目同时治理:
- 哪些事件值得记录;
- 哪些字段可以公开;
- 哪些字段必须掩码或禁止进入日志;
- 谁能访问、保存多久、如何导出;
- 如何让页面错误文案与内部诊断彻底分离。
好日志应该让工程师看清故障链路,却不能让任何人从日志中还原用户身份、聊天内容或认证凭据。

更多推荐


所有评论(0)