在HarmonyOS生态中,保障用户隐私和安全是至关重要的设计原则之一。为此,HarmonyOS引入了AccessTokenManager (ATM)作为统一的应用权限管理机制,确保应用在访问系统资源、数据以及与其他应用交互时遵循严格的安全策略。本文将详细介绍ATM的工作原理、权限申请与校验流程,并提供相关代码示例,帮助开发者在HarmonyOS平台上构建安全合规的应用。

ATM概述

ATM基于AccessToken实现,每个应用都有一个独一无二的TokenID,作为其身份标识。ATM利用TokenID来管理应用的权限,确保应用只能在拥有适当权限的情况下访问或操作受保护的资源。

权限保护对象

  • 数据:涵盖个人数据(如照片、联系人)、设备数据(如设备ID)、应用数据。
  • 功能:包括设备功能(如通话、网络访问)和应用功能(如悬浮窗、快捷方式创建)。

权限使用原则

  1. 明确性:权限申请需附带清晰的使用场景和目的说明。
  2. 最小化:仅申请业务功能所必需的权限。
  3. 适时申请:在实际需要权限时动态申请,避免首次启动时频繁弹窗。
  4. 用户体验:尊重用户选择,若权限被拒,不影响应用基本功能。
  5. 系统权限列表:应用权限需从官方定义的权限列表中选取。

权限工作流程

权限申请使用流程
  1. 需求评估:确认操作是否需要特定权限。
  2. 权限申请:在安装包中声明需要的权限。
  3. 用户授权:对于用户授权类权限,使用弹窗请求用户同意。
  4. 权限使用:授权后,应用可执行相应操作。
权限校验流程
  1. 接口保护:根据接口敏感度选择合适权限进行保护。
  2. 访问控制:通过ATM权限校验接口验证访问者权限。
  3. 权限通过:访问者拥有权限后,可正常使用接口功能。

HarmonyOS入门之权限申请_权限

权限等级与类型

权限等级
  • normal:普通权限,风险较小。
  • system_basic:涉及系统基础服务,风险中等。
  • system_core:操作系统核心权限,暂不对第三方应用开放。
权限类型
  • system_grant:系统自动授权,无需用户介入。
  • user_grant:需用户明确同意,涉及敏感操作。

示例

HarmonyOS应用的权限体系涉及应用的APL(Ability Privilege Level)等级和权限类型。应用权限管理遵循严格的访问控制原则,确保应用仅在拥有必要权限的前提下访问资源。

配置文件权限声明

Stage模型

module.json5中声明权限:

1{
2  "module" : {
3    // ...
4    "requestPermissions":[
5      {
6        "name" : "ohos.permission.PERMISSION_NAME",
7        "reason": "$string:reason_for_permission",
8        "usedScene": {
9          "abilities": [
10            "YourAbility"
11          ],
12          "when":"inuse"
13        }
14      }
15    ]
16  }
17}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
FA模型

config.json中声明权限:

1{
2  "module" : {
3    // ...
4    "reqPermissions":[
5      {
6        "name" : "ohos.permission.PERMISSION_NAME",
7        "reason": "$string:reason_for_permission",
8        "usedScene": {
9          "ability": [
10            "YourAbility"
11          ],
12          "when":"inuse"
13        }
14      }
15    ]
16  }
17}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

权限校验与动态申请

校验权限
1 import bundleManager from '@ohos.bundle.bundleManager';
2 import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
3
4 async function checkPermission(permission) {
5  let atManager = abilityAccessCtrl.createAtManager();
6  let tokenId;
7  
8  try {
9    let bundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
10    tokenId = bundleInfo.appInfo.accessTokenId;
11  } catch (err) {
12    console.error(`Error fetching accessTokenId: ${err}`);
13  }
14
15  try {
16    let grantStatus = await atManager.checkAccessToken(tokenId, permission);
17    return grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;
18  } catch (err) {
19    console.error(`Permission check failed: ${err}`);
20  }
21  return false;
22}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
动态申请权限(通用示例)
1 import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
2 import common from '@ohos.app.ability.common';
3
4 async function requestPermission(context, permissions) {
5  let atManager = abilityAccessCtrl.createAtManager();
6  
7  try {
8    let result = await atManager.requestPermissionsFromUser(context, permissions);
9    let authResults = result.authResults;
10    
11    for (let i = 0; i < authResults.length; i++) {
12      if (authResults[i] !== 0) {
13        // 用户未授权,处理逻辑
14        return false;
15      }
16    }
17    // 所有权限均被授权
18    return true;
19  } catch (err) {
20    console.error(`Permission request failed: ${err}`);
21    return false;
22  }
23}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

动态申请授权示例

在UIAbility中申请
1export default class YourAbility extends UIAbility {
2  onWindowStageCreate(windowStage) {
3    const permissions = ['ohos.permission.PERMISSION_NAME'];
4    this.requestPermissions(permissions);
5  }
6
7  async requestPermissions(permissions) {
8    let context = this.context;
9    if (await requestPermission(context, permissions)) {
10      // 权限申请成功,执行相关操作
11    } else {
12      // 引导用户至设置页开启权限
13      openPermissionsInSystemSettings();
14    }
15  }
16}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
引导用户至系统设置
1 function openPermissionsInSystemSettings(context) {
2  let wantInfo = {
3    action: 'action.system.settings.permission',
4    entities: ['com.example.yourapp']
5  };
6  context.startAbility(wantInfo);
7}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
// 假设需要请求麦克风权限
String permission = "ohos.permission.MICROPHONE";

// 检查当前是否已有权限
int result = checkSelfPermission(permission);
if (result == PackageManager.PERMISSION_GRANTED) {
    // 已有权限,执行操作
} else {
    // 未授权,发起请求
    requestPermissions(new String[]{permission}, PERMISSION_REQUEST_CODE);
}

// 处理权限请求结果
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 用户已授权,执行操作
        } else {
            // 用户拒绝授权,给出提示或处理方案
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

总结

通过深入了解和正确应用AccessTokenManager及其权限管理机制,开发者能够在HarmonyOS平台上构建既强大又安全的应用,确保用户数据的隐私与应用生态的健康发展。遵循权限使用的最佳实践,是每个HarmonyOS开发者不可或缺的责任。