鸿蒙文件安全权限高级管控:应用文件私有/公共目录访问控制/文件权限精细化ACL/数据脱敏处理



一、前置思考
1.1 文件安全为何最容易失控
文件安全是最容易出问题的环节:开发图省事把敏感数据明文写文件、把临时文件当永久数据存、导出数据不做脱敏。等到用户隐私泄露或合规审查时,才发现"哪个文件存了什么敏感数据"完全失控。
先看几个真实的文件泄露事故路径:
| 事故 | 发生过程 | 根因 |
|---|---|---|
| 备份还原泄露 | 用户换了新手机,恢复旧备份后敏感文件被第三方读取 | 敏感文件明文存储 |
| 日志泄露手机号 | 开发把用户手机号打到日志里,日志文件被拖走 | 日志未脱敏 |
| 导出文件泄露 | 客服导出客户数据给业务方,文件被转发 | 导出未脱敏 + 无权限管控 |
| 缓存被拖走 | 图片缓存包含身份证照片,cache 目录被读 | 敏感数据放 cache 未加密 |
这些事故的共同点:文件系统没有分级管控,敏感数据以明文躺在可被读取的位置。
1.2 文件安全管控的四个层次
文件安全管控的四个层次:
- 应用文件私有:沙箱内文件默认隔离
- 公共目录控制:相册/媒体库访问需授权
- 文件权限 ACL:精细化控制读写权限
- 数据脱敏:导出/展示时隐藏敏感字段
这四个层次解决的是不同的问题:私有隔离解决"谁能看到",公共控制解决"谁能访问",ACL 解决"能怎么访问",脱敏解决"看到了能不能用"。
1.3 本文结构
本文从文件访问分层模型、ACL 权限模型、URI 临时授权、数据脱敏四个维度展开,并补充敏感文件清单管理和文件生命周期治理等工程化内容。
二、核心原理
2.1 文件访问分层模型
┌─────────────────────────────────────────────┐
│ 应用私有目录 │
│ files/ · cache/ · database/ │
│ 仅本应用可读写(沙箱隔离) │
├─────────────────────────────────────────────┤
│ 共享文件(应用内) │
│ share/ 目录 · 通过 ACL 控制 │
├─────────────────────────────────────────────┤
│ 公共媒体库 │
│ 相册/视频/音频 · 需用户授权 + URI │
├─────────────────────────────────────────────┤
│ 系统级/其他应用文件 │
│ 默认拒绝 · 仅系统能力可访问 │
└─────────────────────────────────────────────┘
各层的核心规则:
应用私有目录:files/ 存持久数据、cache/ 存可清理缓存、database/ 存数据库、preferences/ 存首选项。只有本应用进程能访问,其他应用即使知道路径也会被 SELinux 拒绝。
共享文件:应用内需要跨模块共享的文件(如生成的导出文件),放到显式共享目录,通过 ACL 控制谁能读谁不能读。
公共媒体库:用户的照片/视频/音频归系统媒体库管理,应用访问必须走用户授权(PhotoViewPicker 或权限申请)。
系统级文件:/system、/data 其他区域、/proc 等,普通应用一律拒绝。
2.2 文件 ACL 权限模型
ACL(Access Control List)实现文件级精细授权:
文件: shared_doc.pdf
ACL:
owner: 读写 (本应用)
group: 只读 (同组应用)
other: 无权限 (其他应用)
| 文件 | ACL | 加密 | 用途 |
|---|---|---|---|
| user_prefs.json | rw------- | 加密 | 用户偏好 |
| photo_cache.jpg | rw------- | 明文 | 缓存(可重建) |
| shared_doc.pdf | r–r–r– | 加密 | 对外分享 |
| media_photo.jpg | URI授权 | 明文 | 公共媒体库 |
ACL 设计的三条原则:
(1)最小权限
每个文件只授予完成任务所需的最小访问范围。默认 rw-------(仅 owner 读写),需要共享才放宽。不要图省事把文件权限全开成 world-readable。
(2)权限与加密组合
ACL 控制"谁能打开文件",加密控制"打开后能不能看懂"。敏感文件即使 ACL 被绕过(如 root 读取),加密兜底保证内容不可读。两者是互补关系,不是替代关系。
(3)按数据敏感度分级
| 敏感度 | 文件示例 | 保护策略 |
|---|---|---|
| 高 | 密钥备份、支付凭据 | ACL 最小 + 强加密 + 权限校验 |
| 中 | 用户资料、导出报表 | ACL 受控 + 加密 |
| 低 | 图片缓存、临时文件 | ACL 默认,可不加密 |
2.3 URI 临时授权
跨应用分享文件走 URI 临时授权:
应用A(分享方) 应用B(接收方)
│ │
│ 1. 生成文件 URI │
│ 2. 授权: { uri, mode, expire } │
│ 3. 传递 URI ──────────────────→ │
│ │ 4. 校验授权时效
│ │ 5. 按 mode 访问
│ │ 6. 过期后失效
▼ ▼
授权属性:URI + 模式(只读/读写)+ 时效(10分钟/30分钟)。
URI 临时授权解决的是"应用 B 如何访问应用 A 的私有文件"的问题。如果没有这个机制,要么把文件复制到公共区域(泄露风险),要么给 B 永久访问权(后门风险)。临时授权让"共享"和"安全"可以兼得:
- 一次性:授权只针对单个 URI,不是整个目录
- 有时效:授权过期后自动失效,不留后门
- 可限定模式:只读/读写分离,只分享需要的权限
- 用户可感知:授权行为由系统管理,可审计
2.4 数据脱敏
导出/展示敏感数据时必须脱敏:
| 字段 | 原文 | 脱敏规则 | 脱敏结果 |
|---|---|---|---|
| 手机号 | 13812345678 | 保留前3后4 | 138****5678 |
| 身份证 | 110101199003074512 | 保留前6后4 | 110101********4512 |
| 银行卡 | 6222021234567890123 | 保留前4后4 | 6222*************0123 |
| 邮箱 | zhangsan@example.com | 用户名中段隐藏 | zh***n@example.com |
// 脱敏工具示意
export class MaskUtil {
static maskPhone(phone: string): string {
if (phone.length < 7) {
return phone;
}
return phone.substring(0, 3) + '****' + phone.substring(phone.length - 4);
}
static maskIdCard(id: string): string {
if (id.length < 10) {
return id;
}
return id.substring(0, 6) + '********' + id.substring(id.length - 4);
}
}
脱敏的三个落地场景:
- 导出脱敏:CSV/Excel 导出前,敏感列走脱敏管道
- 日志脱敏:日志打印统一走脱敏工具,手机号/身份证/Token 自动打码
- 界面脱敏:列表/详情页展示敏感信息时按角色决定是否打码(客服看全量、普通员工看脱敏)
三、典型攻击场景还原
3.1 场景一:备份还原窃取数据
攻击者操作:
1. 诱导用户打开备份文件/云备份
2. 用工具读取备份中的数据库和文件
被拦截的环节:
① 敏感文件已加密落盘,备份文件里是密文
② 解密密钥在 HUKS 内,换设备后密钥不存在,无法解密
③ 即使拿到密文也无法还原明文
3.2 场景二:目录遍历攻击
攻击者操作:
1. 恶意应用尝试通过 ../ 路径穿越读取其他应用目录
2. 尝试访问 /data/xxx 系统目录
被拦截的环节:
① 沙箱隔离:路径即使解析成功,SELinux 上下文不匹配 → EACCES
② 系统目录对普通应用完全不可见
③ URI 授权范围限定:无法通过授权机制越权访问
3.3 场景三:导出文件泄露
攻击者操作(或事故):
1. 客服导出客户数据 → 文件通过 IM 转发
2. 接收方打开文件看到全部明文
被拦截的环节:
① 导出走脱敏管道:手机号/身份证打码
② 导出文件加密 + 访问口令(视敏感度)
③ 导出行为审计留痕,可追溯谁导出的
四、实战落地
对应 Demo 页面:entry/src/main/ets/pages/FileSecurityDemo.ets
Demo 包含三个 Tab:
- 文件ACL:展示各类文件的访问范围/ACL/加密状态(私有目录加密、共享文件受控、公共媒体库 URI 授权),支持切换加密状态演示
- URI授权:展示 URI 临时授权记录(URI/目标应用/模式/有效期),支持签发新的临时授权
- 数据脱敏:展示手机号/身份证/银行卡/邮箱的脱敏规则与效果,支持一键执行脱敏
// Demo 核心:签发 URI 临时授权
private grantUri(): void {
const rec: UriGrant = {
uri: 'file://com.example.app/share/export_' +
this.uriGrants.length.toString() + '.csv',
targetApp: 'com.huawei.filemanager', mode: '只读',
expire: '30分钟后', status: '✅ 有效'
};
const newGrants: UriGrant[] = this.uriGrants.slice(0);
newGrants.unshift(rec);
this.uriGrants = newGrants;
this.fileSummary = '已签发 URI 临时授权:导出文件仅供文件管理器 30 分钟内访问';
}
4.1 敏感文件清单管理
文件安全的第一步是"知道自己有哪些敏感文件"。建立敏感文件清单:
| 字段 | 说明 | 示例 |
|---|---|---|
| 文件路径 | 实际存储位置 | /files/export/20260802.csv |
| 数据内容 | 包含哪些敏感字段 | 手机号、身份证 |
| 加密状态 | 是否加密 | HUKS AES-256 |
| ACL | 访问范围 | rw------- |
| 生命周期 | 何时创建/何时清理 | 保留 30 天 |
| 负责人 | 谁负责 | 数据安全组 |
清单要动态维护:新增敏感字段时同步更新清单,发版前对照清单核查加密/ACL 是否到位。
4.2 文件生命周期治理
文件不是"写了就不管",生命周期治理覆盖:创建 → 使用 → 归档 → 清理:
创建:按敏感度分级加密落盘
│
使用:按 ACL 授权访问,访问留痕
│
归档:过期数据加密归档(冷存储)
│
清理:到期清理 + 安全删除(覆盖写/加密销毁)
重点动作:
- 安全删除:敏感文件删除时做覆盖写(写随机数据后再删),防止磁盘残留被恢复
- 到期清理:临时文件、导出文件设定生命周期,到期自动清理
- 清理审计:清理动作记录日志,防止"删错了"
4.3 日志与导出强制脱敏的工程实现
脱敏要"强制"而不是"靠自觉",工程上三个手段:
- 统一日志封装:全项目禁止直接 console.log,统一走 LogUtil(内部强制脱敏)
- 导出管道化:导出数据必须经过 ExportPipeline(内部执行脱敏规则)
- CI 检查:静态扫描检测明文日志、未脱敏导出代码
五、避坑速查
| 坑 | 现象 | 原因 | 解决 |
|---|---|---|---|
| 敏感文件明文存储 | 备份被还原泄露 | 未加密写文件 | 敏感数据加密(HUKS+AES)落盘 |
| 把 cache 当永久目录 | 数据丢失 | cache 可被清理 | 持久数据放 files/ |
| 分享授权永久有效 | 授权被滥用 | URI 授权未设时效 | 授权带 TTL + 用后撤销 |
| 导出未脱敏 | 合规审查失败 | 直接导出原始数据 | 导出前统一走脱敏管道 |
| ACL 配置过宽 | 其他应用可读 | 默认权限未收紧 | 遵循最小权限设置 ACL |
| 明文日志泄露 | 日志里有手机号 | 日志未脱敏 | 日志层统一脱敏 |
| 文件删除不彻底 | 磁盘残留被恢复 | 普通 delete 可恢复 | 覆盖写 + 加密销毁 |
| 导出文件无管控 | 文件被随意转发 | 无权限/口令保护 | 加密 + 口令 + 审计 |
| 忽略文件备份 | 备份文件明文 | 备份未加密 | 备份走加密通道 |
六、总结
文件安全管控四板斧:
- 私有隔离:应用文件默认私有,沙箱兜底
- 公共受控:公共目录访问走 URI + 用户授权
- ACL 精细:文件级读写权限精细化管控
- 脱敏兜底:导出/展示统一脱敏,防明文泄露
落地建议:
- 建立"敏感文件清单",明确每个文件存储位置、加密策略、ACL
- 所有跨应用文件分享走 URI 临时授权
- 脱敏做成统一工具,导出/日志/展示强制走脱敏管道
- 敏感文件纳入生命周期治理:加密落盘、到期清理、安全删除
- 日志统一封装,禁止裸打日志,杜绝明文泄露
文件安全是"细节决定成败"的领域——没有任何单一手段能挡住所有攻击,但"私有隔离 + 加密 + ACL + 脱敏"的组合,能让攻击者即使拿到了文件也读不懂、用不了、拿不出。
更多推荐




所有评论(0)