Appearance
应用沙箱
HarmonyOS 采用应用沙箱机制,每个应用运行在独立的隔离环境中。
1. 沙箱架构
┌─────────────────────────────────────────┐
│ HarmonyOS System │
├─────────────────────────────────────────┤
│ App Sandbox 1 │ App Sandbox 2 │
│ ┌───────────┐ │ ┌───────────┐ │
│ │ EntryAbility│ │ │ EntryAbility│ │
│ │ Data/ │ │ │ Data/ │ │
│ │ Cache/ │ │ │ Cache/ │ │
│ │ Files/ │ │ │ Files/ │ │
│ │ TokenID: A │ │ │ TokenID: B │ │
│ └───────────┘ │ └───────────┘ │
├─────────────────────────────────────────┤
│ Kernel (隔离层) │
└─────────────────────────────────────────┘沙箱特点
| 特性 | 说明 |
|---|---|
| 进程隔离 | 每个应用独立进程 |
| 文件隔离 | 应用数据目录独立 |
| 权限隔离 | 基于 TokenID 的访问控制 |
| 网络隔离 | 独立的网络命名空间 |
2. 沙箱目录结构
应用沙箱目录:
/data/app/el1/bundle/public/com.example.myapp/
├── entry/
│ ├── databases/ # 数据库文件
│ ├── cache/ # 缓存文件
│ ├── files/ # 普通文件
│ ├── preferences/ # 首选项配置
│ └── lib/ # 原生库
└── ...目录访问 API
typescript
import { fileIo } from '@kit.ArkIO';
// 获取应用目录
let context = getContext() as common.UIAbilityContext;
// 缓存目录
let cacheDir = context.cacheDir;
// 文件目录
let filesDir = context.filesDir;
// 数据库目录
let databaseDir = context.databaseDir;
// 首选项目录
let preferencesDir = context.preferencesDir;
// 读取文件
let filePath = `${filesDir}/data.txt`;
let content = await fileIo.readFile(filePath);3. 沙箱隔离机制
进程隔离
每个应用:
- 独立的 Linux 进程
- 独立的 UID/GID
- 独立的内存空间
- 独立的线程池文件隔离
typescript
// ❌ 无法直接访问其他应用的文件
let otherAppPath = '/data/app/el1/bundle/public/com.other.app/files/data.txt';
// 访问会被内核拒绝
// ✅ 通过共享文件 URI 方式访问
let uri = 'file://shared/xxx';
let content = await fileIo.readFile(uri);权限隔离
typescript
// 即使知道其他应用的 TokenID,也无法冒充
let myTokenId = getTokenId();
// 系统会验证 TokenID 与调用者身份匹配4. 跨应用数据共享
方式一:FileProvider
typescript
// 提供方应用
import { dataShare } from '@kit.ArkDataShare';
// 创建共享文件 URI
let uri = dataShare.getDataShareUri('com.example.provider', 'files/data.txt');
// 接收方应用
let content = await fileIo.readFile(uri);方式二:Want 传参
typescript
// 启动方
let want: Want = {
bundleName: 'com.example.other',
abilityName: 'DetailAbility',
parameters: {
'data': JSON.stringify({ id: 1, name: 'test' })
}
};
context.startAbility(want);
// 接收方
let params = this.context.want.parameters;
let data = JSON.parse(params['data'] as string);方式三:分布式数据对象
typescript
import { distributedDataObject } from '@kit.ArkDistributedDataObject';
// 创建分布式对象
let obj = distributedDataObject.create({
namespace: 'my_namespace',
objectID: 'shared_object'
});
// 设置值(其他设备/应用可访问)
obj.put('key', 'value');5. URI 安全
URI 授权
typescript
import { uriAuthority } from '@kit.ArkURI';
// 授予临时 URI 权限
await uriAuthority.grantUriPermission({
targetBundle: 'com.example.other',
uri: 'file://shared/data.txt',
mode: uriAuthority.GRANT_READ_ONLY
});
// 撤销权限
await uriAuthority.revokeUriPermission({
targetBundle: 'com.example.other',
uri: 'file://shared/data.txt'
});URI 校验
typescript
// 校验 URI 是否合法
function isValidUri(uri: string): boolean {
try {
new URL(uri);
return true;
} catch {
return false;
}
}
// 防止路径遍历攻击
function sanitizePath(path: string): string {
// 移除 ../ 等危险字符
return path.replace(/\.\.\//g, '');
}6. 沙箱安全最佳实践
1. 最小化文件暴露
typescript
// ✅ 推荐:只共享必要的文件
let shareableFiles = ['public_report.pdf'];
// ❌ 不推荐:共享整个目录
// grantPermission('/data/app/.../files/*');2. 及时撤销权限
typescript
// 使用完毕后立即撤销
async function shareFile(targetBundle: string, uri: string) {
await uriAuthority.grantUriPermission({ targetBundle, uri });
try {
// 使用文件
await doSomething(uri);
} finally {
// 确保撤销
await uriAuthority.revokeUriPermission({ targetBundle, uri });
}
}3. 敏感数据加密存储
typescript
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
// 加密存储
async function saveSensitiveData(data: string) {
let encryptor = await cryptoFramework.createEncryptor('AES128');
let encrypted = await encryptor.encrypt(data, { keyAlias: 'my_key' });
await fileIo.writeFile(`${filesDir}/sensitive.dat`, encrypted);
}7. 面试高频问题
Q1: 应用沙箱的作用是什么?
答:沙箱隔离每个应用的运行环境,防止恶意应用访问其他应用的数据或系统资源,是鸿蒙安全模型的基础。
Q2: 如何实现跨应用数据共享?
答:
- FileProvider + URI 授权
- Want 参数传递
- 分布式数据对象
- 公共存储服务(如相册)
Q3: 沙箱目录有哪些?
答:cacheDir(缓存)、filesDir(文件)、databaseDir(数据库)、preferencesDir(首选项)。
8. 与 Android 对照
| 概念 | HarmonyOS | Android |
|---|---|---|
| 沙箱目录 | /data/app/el1/bundle/ | /data/data/package/ |
| 缓存目录 | cacheDir | getCacheDir() |
| 文件目录 | filesDir | getFilesDir() |
| URI 授权 | grantUriPermission | grantUriPermission |
| 进程隔离 | 独立进程 | 独立进程 |
面试提示:沙箱机制是鸿蒙安全的基础,需理解隔离原理和跨应用共享方式。