HarmonyOS安全机制详解——应用权限申请与校验
1. HarmonyOS安全体系概述
HarmonyOS构建了全方位的安全防护体系,基于"正确的人,通过正确的设备,正确的使用数据"的安全理念,为应用开发提供了多层次的安全保障机制。这套体系从设备安全、数据安全到应用安全,形成了完整的纵深防御架构。
1.1 安全架构层次
HarmonyOS安全体系包含以下关键层次:
- 设备安全层:基于硬件信任根,提供芯片级安全能力
- 系统安全层:通过内核安全机制保证系统完整性
- 应用安全层:应用沙箱、权限管理、身份认证
- 数据安全层:分级加密、分布式数据保护
1.2 权限管理的基本理念
HarmonyOS权限管理遵循最小权限原则和用户可知可控原则。应用只能在获得相应权限的情况下,才能执行受限操作或访问受保护的数据。权限的授予需要经过用户的明确同意,并且用户可以随时撤销已授予的权限。
2. 权限类型与分类
2.1 权限等级体系
HarmonyOS将权限分为三个安全等级,不同等级的权限在申请和授权方式上存在差异:
2.1.1 normal权限(普通权限)
普通权限允许应用访问超出沙箱的受限数据或资源,但这些数据或资源对用户隐私或其他应用风险很小。普通权限在应用安装时自动授予,无需用户动态授权。
示例权限:
ohos.permission.INTERNET(网络访问)ohos.permission.GET_NETWORK_INFO(获取网络信息)ohos.permission.GET_BUNDLE_INFO(获取应用信息)
2.1.2 restricted权限(受限权限)
受限权限允许应用访问涉及用户隐私的敏感数据,或使用受限的资源。这类权限需要应用在运行时动态申请,并由用户明确授权。
示例权限:
ohos.permission.READ_CONTACTS(读取联系人)ohos.permission.READ_CALENDAR(读取日历)ohos.permission.READ_MEDIA(读取媒体文件)
2.1.3 system_grant权限(系统授权权限)
系统授权权限涉及系统核心功能或高度敏感的用户数据,通常只有系统应用或特定场景下的应用才能获得。这类权限需要在应用商店审核时申请,并由系统根据签名和特权配置进行授权。
示例权限:
ohos.permission.ACCESS_BIOMETRIC(生物特征识别)ohos.permission.ACCESS_BIOMETRIC_INTERNAL(内部生物特征识别)
2.2 权限分组管理
为了简化用户授权体验,HarmonyOS将功能相关的权限进行分组。当用户授予某个权限组中的某个权限时,系统会自动授予该权限组内的其他权限。
3. 权限申请与配置
3.1 权限声明配置
在应用的配置文件中明确定义应用需要的所有权限,这是权限管理的基础步骤。
module.json5配置文件示例:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.CAMERA",
"reason": "$string:camera_permission_reason",
"usedScene": {
"abilities": [
"MainAbility"
],
"when": "inuse"
}
},
{
"name": "ohos.permission.READ_CONTACTS",
"reason": "需要读取联系人以快速分享内容",
"usedScene": {
"abilities": [
"MainAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.LOCATION",
"reason": "提供基于位置的服务",
"usedScene": {
"abilities": [
"LocationAbility"
],
"when": "inuse"
}
}
]
}
}
字符串资源文件(string.json):
{
"string": [
{
"name": "camera_permission_reason",
"value": "需要使用相机进行拍照和扫码"
}
]
}
3.2 动态权限申请
对于restricted权限,需要在运行时动态向用户申请授权。
完整的动态权限申请示例:
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';
import { BusinessError } from '@ohos.base';
const TAG = 'PermissionManager';
const DOMAIN_NUMBER = 0xFF00;
class PermissionManager {
private context: common.UIAbilityContext;
private atManager: abilityAccessCtrl.AtManager;
constructor(context: common.UIAbilityContext) {
this.context = context;
this.atManager = abilityAccessCtrl.createAtManager();
}
// 检查权限状态
async checkPermission(permission: string): Promise<abilityAccessCtrl.GrantStatus> {
try {
const grantStatus = await this.atManager.checkAccessToken(this.context.tokenId, permission);
hilog.info(DOMAIN_NUMBER, TAG, `权限 ${permission} 状态: ${grantStatus}`);
return grantStatus;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `检查权限失败: code=${err.code}, message=${err.message}`);
return abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
}
}
// 申请单个权限
async requestPermission(permission: string): Promise<boolean> {
try {
// 先检查当前权限状态
const currentStatus = await this.checkPermission(permission);
if (currentStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
hilog.info(DOMAIN_NUMBER, TAG, `权限 ${permission} 已授予`);
return true;
}
// 需要申请权限
const grantStatus = await this.atManager.requestPermissionsFromUser(this.context, [permission]);
if (grantStatus.authResults[permission] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
hilog.info(DOMAIN_NUMBER, TAG, `权限 ${permission} 申请成功`);
return true;
} else {
hilog.warn(DOMAIN_NUMBER, TAG, `权限 ${permission} 被拒绝`);
this.showPermissionGuide(permission);
return false;
}
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `申请权限失败: code=${err.code}, message=${err.message}`);
return false;
}
}
// 批量申请权限
async requestMultiplePermissions(permissions: string[]): Promise<{ [permission: string]: boolean }> {
const results: { [permission: string]: boolean } = {};
try {
// 先检查所有权限的当前状态
for (const permission of permissions) {
const status = await this.checkPermission(permission);
if (status === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
results[permission] = true;
}
}
// 筛选出需要申请的权限
const permissionsToRequest = permissions.filter(p => !results[p]);
if (permissionsToRequest.length > 0) {
const grantStatus = await this.atManager.requestPermissionsFromUser(this.context, permissionsToRequest);
// 处理授权结果
for (const permission of permissionsToRequest) {
results[permission] =
grantStatus.authResults[permission] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
}
}
return results;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `批量申请权限失败: code=${err.code}, message=${err.message}`);
// 设置默认结果
for (const permission of permissions) {
results[permission] = false;
}
return results;
}
}
// 显示权限引导说明
private showPermissionGuide(permission: string): void {
// 根据权限类型提供不同的引导信息
const guideMessages: { [key: string]: string } = {
'ohos.permission.CAMERA': '相机权限被拒绝,无法使用拍照和扫码功能。请前往设置中开启权限。',
'ohos.permission.MICROPHONE': '麦克风权限被拒绝,无法进行录音。请前往设置中开启权限。',
'ohos.permission.LOCATION': '位置权限被拒绝,无法提供基于位置的服务。请前往设置中开启权限。'
};
const message = guideMessages[permission] || '所需权限被拒绝,部分功能可能无法正常使用。';
// 这里可以显示对话框引导用户去设置中开启权限
hilog.warn(DOMAIN_NUMBER, TAG, message);
}
// 检查所有必要权限
async checkAllRequiredPermissions(): Promise<boolean> {
const requiredPermissions = [
'ohos.permission.CAMERA',
'ohos.permission.MICROPHONE',
'ohos.permission.LOCATION'
];
try {
for (const permission of requiredPermissions) {
const status = await this.checkPermission(permission);
if (status !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
return false;
}
}
return true;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `检查必要权限失败: ${err.message}`);
return false;
}
}
}
export default PermissionManager;
3.3 权限使用的最佳实践
渐进式权限申请策略:
import { BusinessError } from '@ohos.base';
class CameraService {
private permissionManager: PermissionManager;
private isCameraAvailable: boolean = false;
constructor(permissionManager: PermissionManager) {
this.permissionManager = permissionManager;
}
// 按需申请相机权限
async initializeCamera(): Promise<boolean> {
try {
// 检查相机权限
const hasPermission = await this.permissionManager.requestPermission('ohos.permission.CAMERA');
if (!hasPermission) {
hilog.warn(DOMAIN_NUMBER, TAG, '相机权限未授予,无法使用相机功能');
this.isCameraAvailable = false;
return false;
}
// 权限已授予,初始化相机
await this.setupCamera();
this.isCameraAvailable = true;
return true;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `初始化相机失败: ${err.message}`);
this.isCameraAvailable = false;
return false;
}
}
// 使用相机功能前的权限检查
async takePhoto(): Promise<boolean> {
if (!this.isCameraAvailable) {
const hasPermission = await this.initializeCamera();
if (!hasPermission) {
return false;
}
}
// 执行拍照逻辑
return this.captureImage();
}
private async setupCamera(): Promise<void> {
// 相机初始化逻辑
hilog.info(DOMAIN_NUMBER, TAG, '相机初始化完成');
}
private async captureImage(): Promise<boolean> {
// 拍照逻辑
hilog.info(DOMAIN_NUMBER, TAG, '执行拍照操作');
return true;
}
}
4. 权限校验与安全实践
4.1 运行时权限验证
在每次执行敏感操作前,都需要验证当前是否具有相应的权限。
操作前权限验证示例:
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import { BusinessError } from '@ohos.base';
class SecureOperationManager {
private atManager: abilityAccessCtrl.AtManager;
private context: common.UIAbilityContext;
constructor(context: common.UIAbilityContext) {
this.context = context;
this.atManager = abilityAccessCtrl.createAtManager();
}
// 执行敏感操作前的权限验证
async performSecureOperation(operationType: string, data?: any): Promise<boolean> {
// 定义操作类型与所需权限的映射
const operationPermissions: { [key: string]: string } = {
'read_contacts': 'ohos.permission.READ_CONTACTS',
'write_contacts': 'ohos.permission.WRITE_CONTACTS',
'access_location': 'ohos.permission.LOCATION',
'use_camera': 'ohos.permission.CAMERA',
'record_audio': 'ohos.permission.MICROPHONE'
};
const requiredPermission = operationPermissions[operationType];
if (!requiredPermission) {
hilog.error(DOMAIN_NUMBER, TAG, `未知操作类型: ${operationType}`);
return false;
}
try {
// 验证权限
const grantStatus = await this.atManager.checkAccessToken(this.context.tokenId, requiredPermission);
if (grantStatus !== abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
hilog.warn(DOMAIN_NUMBER, TAG, `执行 ${operationType} 操作缺少权限: ${requiredPermission}`);
return false;
}
// 执行实际操作
return await this.executeOperation(operationType, data);
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `执行安全操作失败: ${err.message}`);
return false;
}
}
private async executeOperation(operationType: string, data?: any): Promise<boolean> {
switch (operationType) {
case 'read_contacts':
return await this.readContacts();
case 'use_camera':
return await this.useCamera();
case 'access_location':
return await this.accessLocation();
default:
hilog.warn(DOMAIN_NUMBER, TAG, `未实现的操作类型: ${operationType}`);
return false;
}
}
private async readContacts(): Promise<boolean> {
// 读取联系人逻辑
hilog.info(DOMAIN_NUMBER, TAG, '执行读取联系人操作');
return true;
}
private async useCamera(): Promise<boolean> {
// 使用相机逻辑
hilog.info(DOMAIN_NUMBER, TAG, '执行相机操作');
return true;
}
private async accessLocation(): Promise<boolean> {
// 访问位置逻辑
hilog.info(DOMAIN_NUMBER, TAG, '执行位置访问操作');
return true;
}
}
4.2 持续权限监控
应用需要监控权限状态的变化,及时调整功能可用性。
权限状态监控示例:
import commonEventManager from '@ohos.commonEventManager';
import { BusinessError } from '@ohos.base';
class PermissionMonitor {
private context: common.UIAbilityContext;
private permissionListeners: Map<string, (granted: boolean) => void> = new Map();
constructor(context: common.UIAbilityContext) {
this.context = context;
this.setupPermissionMonitor();
}
// 设置权限变更监听
private setupPermissionMonitor(): void {
try {
commonEventManager.createSubscriber({
events: ['usual.event.security.PERMISSION_CHANGED']
}, (err: BusinessError, subscriber) => {
if (err) {
hilog.error(DOMAIN_NUMBER, TAG, `创建权限监听器失败: ${err.message}`);
return;
}
commonEventManager.subscribe(subscriber, (err: BusinessError, data) => {
if (err) {
hilog.error(DOMAIN_NUMBER, TAG, `权限变更监听失败: ${err.message}`);
return;
}
this.handlePermissionChange(data);
});
});
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `设置权限监控失败: ${err.message}`);
}
}
private handlePermissionChange(eventData: any): void {
// 处理权限变更事件
const changedPermissions = eventData.parameters?.permissions || [];
hilog.info(DOMAIN_NUMBER, TAG, `检测到权限变更: ${JSON.stringify(changedPermissions)}`);
// 通知所有监听器
for (const [permission, listener] of this.permissionListeners) {
if (changedPermissions.includes(permission)) {
this.checkAndNotifyPermissionChange(permission, listener);
}
}
}
private async checkAndNotifyPermissionChange(permission: string, listener: (granted: boolean) => void): Promise<void> {
try {
const atManager = abilityAccessCtrl.createAtManager();
const grantStatus = await atManager.checkAccessToken(this.context.tokenId, permission);
const granted = grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
listener(granted);
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `检查权限状态失败: ${err.message}`);
}
}
// 注册权限变更监听器
addPermissionListener(permission: string, listener: (granted: boolean) => void): void {
this.permissionListeners.set(permission, listener);
}
// 移除权限变更监听器
removePermissionListener(permission: string): void {
this.permissionListeners.delete(permission);
}
}
5. 敏感数据保护实践
5.1 关键资产存储保护
对于高度敏感的数据,应使用HarmonyOS提供的关键资产存储服务(Asset Store)进行保护。
关键资产存储示例:
import assetStore from '@ohos.security.assetStore';
class SensitiveDataManager {
// 存储敏感数据
async storeSensitiveData(key: string, data: string): Promise<boolean> {
try {
const options: assetStore.AssetOptions = {
alias: key, // 资产别名
// 设置访问控制策略
accessibility: assetStore.AssetAccessibility.ASSET_ACCESSIBLE_AFTER_FIRST_UNLOCK,
// 需要用户认证
requirePasswordSet: true,
// 认证超时时间(毫秒)
authTimeout: 30000
};
await assetStore.store(this.context, options, data);
hilog.info(DOMAIN_NUMBER, TAG, `敏感数据存储成功: ${key}`);
return true;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `存储敏感数据失败: ${err.message}`);
return false;
}
}
// 检索敏感数据
async retrieveSensitiveData(key: string): Promise<string | null> {
try {
const data = await assetStore.retrieve(this.context, key);
hilog.info(DOMAIN_NUMBER, TAG, `敏感数据检索成功: ${key}`);
return data;
} catch (error) {
const err = error as BusinessError;
if (err.code === 401) {
hilog.warn(DOMAIN_NUMBER, TAG, `用户认证失败或已超时: ${key}`);
} else {
hilog.error(DOMAIN_NUMBER, TAG, `检索敏感数据失败: ${err.message}`);
}
return null;
}
}
// 删除敏感数据
async deleteSensitiveData(key: string): Promise<boolean> {
try {
await assetStore.delete(this.context, key);
hilog.info(DOMAIN_NUMBER, TAG, `敏感数据删除成功: ${key}`);
return true;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `删除敏感数据失败: ${err.message}`);
return false;
}
}
}
5.2 分级数据加密保护
根据数据的安全等级,采用不同的加密保护策略。
分级数据加密示例:
import huks from '@ohos.security.huks';
class DataEncryptionManager {
// 生成加密密钥
async generateEncryptionKey(keyAlias: string): Promise<boolean> {
const properties: huks.HuksParam[] = [
{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
},
{
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
},
{
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
},
{
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_GCM
},
{
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE
}
];
const options: huks.HuksOptions = {
properties: properties
};
try {
await huks.generateKeyItem(keyAlias, options);
hilog.info(DOMAIN_NUMBER, TAG, `加密密钥生成成功: ${keyAlias}`);
return true;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `生成加密密钥失败: ${err.message}`);
return false;
}
}
// 加密数据
async encryptData(keyAlias: string, data: Uint8Array): Promise<Uint8Array | null> {
const properties: huks.HuksParam[] = [
{
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_AES
},
{
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
},
{
tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
value: huks.HuksCipherMode.HUKS_MODE_GCM
},
{
tag: huks.HuksTag.HUKS_TAG_PADDING,
value: huks.HuksKeyPadding.HUKS_PADDING_NONE
}
];
const options: huks.HuksOptions = {
properties: properties,
inData: data
};
try {
const result = await huks.encrypt(keyAlias, options);
hilog.info(DOMAIN_NUMBER, TAG, '数据加密成功');
return result.outData as Uint8Array;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `数据加密失败: ${err.message}`);
return null;
}
}
}
6. 分布式场景下的权限管理
6.1 跨设备权限校验
在分布式场景下,需要确保数据在跨设备传输时的权限一致性。
分布式权限验证示例:
import distributedPermission from '@ohos.distributedPermission';
class DistributedPermissionManager {
// 验证跨设备数据访问权限
async verifyCrossDevicePermission(
deviceId: string,
permission: string,
dataSensitivity: number
): Promise<boolean> {
try {
// 检查目标设备的安全等级
const deviceSecurityLevel = await this.getDeviceSecurityLevel(deviceId);
// 根据数据敏感度等级和设备安全等级进行访问控制
if (!this.isDataTransferAllowed(dataSensitivity, deviceSecurityLevel)) {
hilog.warn(DOMAIN_NUMBER, TAG,
`数据安全等级 ${dataSensitivity} 不允许传输到安全等级 ${deviceSecurityLevel} 的设备`);
return false;
}
// 验证目标设备上的权限
const result = await distributedPermission.verifyPermissionFromRemote(deviceId, permission);
hilog.info(DOMAIN_NUMBER, TAG, `跨设备权限验证结果: ${result}`);
return result;
} catch (error) {
const err = error as BusinessError;
hilog.error(DOMAIN_NUMBER, TAG, `跨设备权限验证失败: ${err.message}`);
return false;
}
}
// 检查设备安全等级
private async getDeviceSecurityLevel(deviceId: string): Promise<number> {
// 实际实现中需要调用设备管理相关API
// 这里返回模拟数据
const securityLevels: { [deviceId: string]: number } = {
'device_phone': 3, // SL3
'device_watch': 1, // SL1
'device_tablet': 3 // SL3
};
return securityLevels[deviceId] || 1;
}
// 检查数据是否允许传输
private isDataTransferAllowed(dataSensitivity: number, deviceSecurityLevel: number): boolean {
// 根据数据安全标签和设备安全等级进行访问控制
const accessControlMatrix: { [level: number]: number[] } = {
1: [1], // SL1设备只能访问S1数据
2: [1, 2], // SL2设备可访问S1-S2数据
3: [1, 2, 3], // SL3设备可访问S1-S3数据
4: [1, 2, 3, 4], // SL4设备可访问所有数据
5: [1, 2, 3, 4] // SL5设备可访问所有数据
};
const allowedSensitivities = accessControlMatrix[deviceSecurityLevel] || [];
return allowedSensitivities.includes(dataSensitivity);
}
}
7. 安全最佳实践与常见问题
7.1 权限申请的最佳实践
- 适时申请:在用户真正需要使用功能时申请权限
- 明确说明:清晰解释权限的用途和好处
- 渐进式授权:按功能模块逐步申请权限
- 优雅降级:权限被拒绝时提供替代方案
7.2 常见错误与解决方案
错误处理示例:
class PermissionErrorHandler {
// 处理权限相关的错误
static handlePermissionError(error: BusinessError, permission: string): void {
switch (error.code) {
case 201: // 权限被拒绝
hilog.warn(DOMAIN_NUMBER, TAG, `权限 ${permission} 被用户拒绝`);
this.showAlternativeSolution(permission);
break;
case 202: // 权限未申请
hilog.warn(DOMAIN_NUMBER, TAG, `权限 ${permission} 未申请`);
break;
case 203: // 权限校验失败
hilog.error(DOMAIN_NUMBER, TAG, `权限 ${permission} 校验失败`);
break;
default:
hilog.error(DOMAIN_NUMBER, TAG, `权限错误: code=${error.code}, message=${error.message}`);
}
}
private static showAlternativeSolution(permission: string): void {
const solutions: { [key: string]: string } = {
'ohos.permission.CAMERA': '您可以选择从相册上传图片',
'ohos.permission.MICROPHONE': '您可以使用文本输入代替语音输入',
'ohos.permission.LOCATION': '您可以手动选择位置'
};
const solution = solutions[permission];
if (solution) {
// 显示替代方案提示
hilog.info(DOMAIN_NUMBER, TAG, `替代方案: ${solution}`);
}
}
}
8. 总结
HarmonyOS提供了完善的权限管理和安全保护机制,开发者应该:
- 遵循最小权限原则,只申请必要的权限
- 实施分级保护策略,根据数据敏感度采用不同的保护措施
- 确保用户体验,合理时机申请权限并提供明确说明
- 加强分布式安全,在跨设备场景下维护数据安全
- 实施纵深防御,结合多种安全机制提供全面保护
通过正确使用HarmonyOS的安全机制,不仅可以保护用户数据安全,还能提升应用的可信度和用户体验。
需要参加鸿蒙认证的请点击 鸿蒙认证链接

浙公网安备 33010602011771号