Appearance
权限模型概述
HarmonyOS NEXT 的权限模型基于 TokenID 和 ATM(Access Token Manager)实现细粒度访问控制。
1. 权限模型架构
┌───────────────────────────────────────────┐
│ 应用层 │
│ 申请权限 → 运行时授权 → 访问资源 │
├───────────────────────────────────────────┤
│ ATM (Access Token Manager) │
│ - TokenID 管理 │
│ - 权限校验 │
│ - 访问控制决策 │
├───────────────────────────────────────────┤
│ Kernel / System Services │
│ - 资源访问拦截 │
│ - 权限验证 │
└───────────────────────────────────────────┘核心概念
| 概念 | 说明 |
|---|---|
| TokenID | 应用的唯一身份标识,用于权限校验 |
| ATM | Access Token Manager,权限管理核心服务 |
| Permission | 权限声明,定义可访问的资源或能力 |
| ACL | Access Control List,访问控制列表 |
2. 权限等级分类
HarmonyOS 将权限分为四个等级:
| 等级 | 英文名称 | 说明 | 授权方式 |
|---|---|---|---|
| basic | system_basic | 系统基本权限,应用默认拥有 | 自动授予 |
| normal | normal | 普通权限,低风险 | 安装时自动授予 |
| user_granted | user_granted | 用户敏感权限 | 运行时动态申请 |
| signature | signature | 签名权限,仅系统应用 | 签名匹配自动授予 |
权限等级示例
json5
// module.json5 权限声明
{
"module": {
"requestPermissions": [
// normal 权限(自动授予)
{
"name": "ohos.permission.INTERNET",
"reason": "$string:permission_internet_reason"
},
// user_granted 权限(需要运行时申请)
{
"name": "ohos.permission.CAMERA",
"reason": "$string:permission_camera_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
// signature 权限(仅系统应用)
{
"name": "ohos.permission.MANAGE_DEVICE",
"reason": "$string:permission_device_reason"
}
]
}
}3. TokenID 机制
TokenID 生成流程
应用安装
↓
生成唯一 TokenID
↓
注册到 ATM 服务
↓
权限校验时使用 TokenID 标识应用身份TokenID 获取
typescript
import { bundleManager } from '@kit.ArkKit';
async function getTokenId(): Promise<string> {
let bundleInfo = await bundleManager.getBundleInfoForSelf(
bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT
);
return bundleInfo.tokenId;
}
// 使用
let tokenId = await getTokenId();
console.log(`应用 TokenID: ${tokenId}`);4. 权限校验流程
校验 API
typescript
import { accessControl } from '@kit.ArkKit';
// 检查权限
async function checkPermission(permissionName: string): Promise<number> {
let result = await accessControl.verifyAccessToken({
permissionName: permissionName,
tokenId: await getTokenId()
});
return result; // 0: 允许,非 0: 拒绝
}
// 同步检查
let syncResult = accessControl.verifyAccessTokenSync({
permissionName: 'ohos.permission.CAMERA',
tokenId: tokenId
});校验结果码
| 结果码 | 含义 |
|---|---|
| 0 | PERMISSION_GRANTED(已授权) |
| 1 | PERMISSION_DENIED(已拒绝) |
| 2 | PERMISSION_NOT_FOUND(权限不存在) |
| 3 | PERMISSION_NOT_GRANTED(未授予) |
5. 权限使用场景
典型场景
| 场景 | 所需权限 | 等级 |
|---|---|---|
| 网络访问 | INTERNET | normal |
| 相机拍照 | CAMERA | user_granted |
| 位置定位 | LOCATION | user_granted |
| 麦克风录音 | MICROPHONE | user_granted |
| 读取联系人 | READ_CONTACTS | user_granted |
| 写入文件 | WRITE_MEDIA | user_granted |
| 蓝牙连接 | BLUETOOTH | normal |
| 系统设置 | MANAGE_SETTINGS | signature |
6. 与 Android 权限模型对比
| 特性 | HarmonyOS | Android |
|---|---|---|
| 身份标识 | TokenID | UID/GID |
| 权限管理 | ATM 服务 | PackageManager |
| 权限等级 | basic/normal/user_granted/signature | normal/dangerous/signature |
| 运行时申请 | verifyAccessToken + requestPermissions | checkSelfPermission + requestPermissions |
| 权限组 | 无权限组概念 | Permission Group |
| 一次性授权 | 支持 | 支持(Android 11+) |
7. 面试高频问题
Q1: TokenID 的作用是什么?
答:TokenID 是应用在系统中的唯一身份标识,用于:
- 权限校验时标识应用身份
- 访问控制决策的依据
- 区分不同应用的资源访问
Q2: 权限等级有哪些?区别是什么?
答:
system_basic:系统基本权限,默认授予normal:普通权限,安装时自动授予user_granted:用户敏感权限,需运行时动态申请signature:签名权限,仅签名匹配的系统应用可用
Q3: 运行时权限申请的流程?
答:
- 在
module.json5中声明权限 - 调用
checkAccessToken检查是否已授权 - 未授权则调用
requestPermissionsFromUser申请 - 根据用户授权结果处理后续逻辑
8. 最佳实践
- 最小权限原则:只申请必要的权限
- 及时释放:不再使用的权限及时释放
- 友好提示:申请前向用户说明用途
- 优雅降级:权限被拒时提供替代方案
- 按需申请:在需要使用功能时再申请,而非启动时批量申请
面试提示:权限模型是鸿蒙安全体系的核心,面试常考 TokenID 机制、权限等级和运行时申请流程。