Skip to content

安全模型

1. 安全架构总览

鸿蒙安全架构分层:
┌──────────────────────────────────────────┐
│  应用层安全                               │
│  └── 应用签名 + 权限申请 + 沙箱隔离       │
├──────────────────────────────────────────┤
│  框架层安全                               │
│  └── TokenID/ATM + 能力门限 + URI 权限   │
├──────────────────────────────────────────┤
│  系统服务层安全                           │
│  └── SELinux 强制访问控制 + 域隔离        │
├──────────────────────────────────────────┤
│  内核层安全                               │
│  └── HongMeng Kernel + MPU + 内存保护    │
├──────────────────────────────────────────┤
│  硬件层安全                               │
│  └── TEE + 安全芯片 + 安全启动链          │
└──────────────────────────────────────────┘

2. TokenID 与访问控制

2.1 TokenID 机制

TokenID 是鸿蒙的核心访问控制机制:

TokenID 特性:
├── 每个进程/线程拥有唯一的 TokenID
├── TokenID 包含权限信息和角色信息
├── 访问资源时必须携带 TokenID 进行验证
├── TokenID 不可伪造,由内核分配
└── TokenID 有时间/空间/角色三维约束
TokenID 的三维约束模型:

┌──────────────────────────────────┐
│          空间维度 (空间)           │
│  └── 进程/线程/Ability 级别       │
├──────────────────────────────────┤
│          时间维度 (时效)           │
│  └── Token 有效期 / 一次性使用    │
├──────────────────────────────────┤
│          角色维度 (角色)           │
│  └── 权限组 / 角色组 绑定         │
└──────────────────────────────────┘

2.2 权限等级

权限等级说明示例申请方式
system_core核心系统权限system_monitor系统签名
system_basic基础系统权限ohos.permission.INTERNET自动授予
normal普通权限camera/storage用户授予
dynamic动态权限location/record运行时申请

2.3 权限检查

arkts
import { permission } from '@kit.AbilityKit';

// 1. 检查权限状态
async function checkPermission() {
  const token = await permission.checkAccessToken('ohos.permission.CAMERA');
  console.log('Token: ' + token);

  // token = 0: 无权限
  // token > 0: 有权限
  // token = -1: 权限不存在
}

// 2. 请求权限
async function requestCameraPermission() {
  const permissions = ['ohos.permission.CAMERA'];
  const token = await permission.requestPermissionsFromUser(permissions);

  if (token === 0) {
    console.log('权限已授予');
  } else {
    console.log('权限被拒绝');
  }
}

// 3. 动态权限申请(用户手动弹窗)
// 与 Android onRequestPermissionsResult 类似
// 鸿蒙通过 system.router.pushUrl 弹出权限对话框

2.4 权限声明

json5
// module.json5
{
  "module": {
    "reqPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "需要访问网络",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.CAMERA",
        "reason": "拍照需要",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      }
    ]
  }
}

3. ATM(Ability Token Manager)

3.1 ATM 机制

ATM (Ability Token Manager) 是系统级的能力访问管理器:

ATM 职责:
├── 管理 Ability 的生命周期 Token
├── 验证 Ability 的跨进程访问权限
├── 管理 URI 权限(file:// 和 resource://)
├── 管理 Service 连接
└── 管理跨 Ability 的参数传递

3.2 URI 权限

arkts
// URI 权限:控制文件资源的跨应用访问
import { uri } from '@kit.AbilityKit';

// 1. 授予 URI 权限(临时文件访问权限)
async function grantUriPermission(want: app.Want) {
  const uriPermissionFlags: number = (
    uri.URIPermissionFlag.READ_URI_PERMISSION
    | uri.URIPermissionFlag.WRITE_URI_PERMISSION
  );

  // 授予目标 Ability 读取 URI 的权限
  await this.context.grantUriPermission('com.target.app', uri, uriPermissionFlags);
}

// 2. 撤销 URI 权限
async function revokeUriPermission(want: app.Want) {
  await this.context.revokeUriPermission('com.target.app', uri);
}

3.3 能力门限(Capability)

能力门限是鸿蒙 IPC 机制中的安全传递机制:

IPC 消息传递时,权限内嵌在消息中:
┌─────────────────────────────────────────┐
│  IPC Message                             │
│  ├── 消息头(类型/大小)                   │
│  ├── 消息体(数据内容)                    │
│  └── Capability(能力描述)               │
│       ├── 可访问的资源列表                 │
│       ├── 可执行的命令列表                 │
│       └── 有效期/空间范围                 │
└─────────────────────────────────────────┘

接收方验证:
1. 检查消息来源的 TokenID
2. 验证 Capability 是否包含目标资源
3. 检查有效期和空间范围
4. 通过 → 执行;不通过 → 拒绝

4. 沙箱机制

4.1 应用沙箱

每个应用运行在独立的沙箱中:

沙箱特性:
├── 文件系统隔离:应用只能访问自己的沙箱目录
├── 网络隔离:独立网络命名空间
├── 进程隔离:独立 PID/UID
├── 内存隔离:独立虚拟地址空间
└── 设备能力隔离:摄像头/麦克风等需要权限

4.2 沙箱目录结构

应用的沙箱目录结构:
┌── /data/user/0/<bundleName>/          (应用数据目录)
│   ├── files/                          (内部文件存储)
│   ├── cache/                          (内部缓存)
│   ├── preferences/                    (偏好设置)
│   └── database/                       (数据库)
├── /data/media/0/                      (共享存储/DCIM)
├── /system/                            (系统只读分区)
└── /vendor/                            (厂商分区)

4.3 URI 安全机制

arkts
// URI 访问安全:通过 Uri 而非直接路径访问文件
import { uri } from '@kit.AbilityKit';

// ✅ 正确:通过 URI 访问共享文件
async function shareFile(targetUri: string) {
  // 通过 URI 传递,而非文件路径
  const fileUri = uri.createFileUri('/data/user/0/com.example/myapp/files/doc.pdf');
  // 授予临时权限给目标应用
  await this.context.grantUriPermission(targetUri, fileUri, uri.URIPermissionFlag.READ_URI_PERMISSION);
}

// ❌ 错误:直接拼接文件路径(不安全)
// const filePath = '/data/data/com.example/files/doc.pdf';

5. SELinux

5.1 SELinux 在鸿蒙中的应用

SELinux(Security-Enhanced Linux)提供强制访问控制:

域(Domain)模型:
├── 每个进程/线程运行在特定域中
├── 域之间通过策略规则定义访问权限
├── 默认策略:DENY ALL(拒绝所有未明确允许的访问)
└── 域过渡:通过 exec 触发域切换

示例策略规则:
┌──────────────────────────────────────┐
│ allow app_domain camera_device:chr_file { read write }; │
│ allow system_domain window_service:unix_stream_socket { connect }; │
│ allow init_domain zygote_domain:process { fork signull }; │
└──────────────────────────────────────┘

5.2 SELinux 模式

模式说明适用场景
enforcing强制执行,违规操作被阻止生产环境(默认)
permissive记录违规但不阻止开发调试
disabled禁用 SELinux调试(不推荐)

5.3 与 Android SELinux 对比

维度Android SELinux鸿蒙 SELinux
策略管理sepolicy 编译为二进制init.hrc 配置策略
域划分app/domain/serviceTokenID + ATM 联合管理
类型系统type + role能力门限 + 权限组
默认策略宽松(allow by default)严格(deny by default)

6. 安全启动链

安全启动 Chain of Trust:

┌─────────────────────────────────────┐
│  BootROM(固化在芯片中)              │
│  ├── 验证 Bootloader 签名            │
│  └── 公钥固化在 ROM 中               │
├─────────────────────────────────────┤
│  Bootloader(U-Boot/Fastboot)       │
│  ├── 验证 Kernel 签名               │
│  └── 传递 Device Tree               │
├─────────────────────────────────────┤
│  Kernel(HongMeng Kernel)           │
│  ├── 初始化安全子系统                 │
│  ├── 验证系统分区签名                │
│  └── 挂载根文件系统                  │
├─────────────────────────────────────┤
│  Userspace                         │
│  ├── 验证系统服务签名                │
│  └── 验证应用签名                   │
└─────────────────────────────────────┘

7. 国密算法支持

算法说明应用场景
SM2非对称加密(椭圆曲线)数字签名/密钥交换
SM3密码散列函数数据完整性校验
SM4对称加密(分组密码)数据加密存储
SM9基于身份的密码算法物联网设备认证
arkts
// 国密算法使用示例
import { cryptoFramework } from '@kit.SecurityFrameworkKit';

// SM2 密钥对生成
const keyPair = await cryptoFramework.generateKeyPair({
  algorithm: 'SM2',
  keySize: 256
});

// SM3 哈希
const hash = await cryptoFramework.hash({
  algorithm: 'SM3',
  data: buffer
});

// SM4 加密
const encrypted = await cryptoFramework.encrypt({
  algorithm: 'SM4',
  key: keyPair.publicKey,
  data: buffer,
  mode: 'ECB'
});

8. 应用签名与安全

8.1 应用签名流程

签名流程:
┌─────────────────────────────────────┐
│  1. 生成密钥对                        │
│     → keytool 生成 .p12 密钥文件     │
├─────────────────────────────────────┤
│  2. 生成 CSR                         │
│     → Certificate Signing Request   │
├─────────────────────────────────────┤
│  3. 申请证书                         │
│     → 发布证书 (.cer)               │
│     → 中间证书 (.p7b)               │
├─────────────────────────────────────┤
│  4. 打包签名                         │
│     → 在 DevEco Studio 中配置        │
│     → hvigor 自动签名                │
└─────────────────────────────────────┘

8.2 签名验证

签名验证时机:
├── 安装时:验证签名与 manifest 匹配
├── 运行时:验证跨应用调用的签名一致性
├── 更新时:验证签名与新包匹配(同签名应用才可覆盖更新)
└── 系统服务:验证系统服务的签名身份

9. 🎯 面试高频考点

Q1: 鸿蒙的 TokenID 机制与 Android 的 UID 机制有什么区别?

答要点

  • TokenID 是三维约束(空间/时间/角色),UID 是一维(进程级)
  • TokenID 可动态分配/撤销,UID 固定
  • TokenID 通过 ATM 集中管理,UID 由内核分配
  • TokenID 支持细粒度权限(能力门限),UID 是粗粒度
  • TokenID 与 Ability 生命周期绑定,UID 与进程绑定

Q2: 鸿蒙的沙箱机制如何实现?

答要点

  • 文件系统:每个应用独立沙箱目录,不能访问其他应用目录
  • 网络:独立网络命名空间
  • 内存:独立虚拟地址空间
  • URI 权限:通过 grantUriPermission 实现临时文件共享
  • SELinux:强制域隔离,默认拒绝未授权的域间访问

Q3: 如何申请和检查运行时权限?

答要点

  • 在 module.json5 中声明权限
  • 使用 permission.checkAccessToken() 检查权限
  • 使用 permission.requestPermissionsFromUser() 申请权限
  • 用户通过系统弹窗手动确认
  • 权限分为 normal(自动授予)和 dynamic(需用户确认)
  • 不同权限等级需要不同签名

💡 面试提示:安全是面试重点。重点掌握 TokenID 三维模型ATM 管理URI 权限沙箱隔离 四个核心概念,对比 Android 的 UID/SELinux/PackageManager。