访问控制授权申请
访问控制授权申请
场景介绍
应用的APL(Ability Privilege Level)等级分为normal
、system_basic
和system_core
三个等级,默认情况下,应用的APL等级都为normal
等级。权限类型分为system_grant
和user_grant
两种类型。应用可申请的权限项参见应用权限列表。
本文将从如下场景分别介绍:
配置文件权限声明
应用需要在项目的配置文件中逐个声明所需的权限,否则应用将无法获取授权。
说明:
应用在申请
system_basic
和system_core
等级权限时,需要提升权限等级,因为应用默认的权限等级为normal
。如果应用需要申请高于默认等级的权限,除了在配置文件中进行声明之外,还需要通过ACL方式进行声明使用。
配置文件标签说明如下表所示。
标签 | 是否必填 | 说明 |
---|---|---|
name | 是 | 权限名称。 |
reason | 否 | 描述申请权限的原因。 > 说明:当申请的权限为user_grant权限时,此字段必填。 |
usedScene | 否 | 描述权限使用的场景和时机。 > 说明:当申请的权限为user_grant权限时,此字段必填。 |
abilities | 否 | 标识需要使用到该权限的Ability,标签为数组形式。 适用模型:Stage模型 |
ability | 否 | 标识需要使用到该权限的Ability,标签为数组形式。 适用模型:FA模型 |
when | 否 | 标识权限使用的时机,值为inuse/always 。- inuse:表示为仅允许前台使用。 - always:表示前后台都可使用。 |
Stage模型
使用Stage模型的应用,需要在module.json5配置文件中声明权限。
{
"module" : {
// ...
"requestPermissions":[
{
"name" : "ohos.permission.PERMISSION1",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"FormAbility"
],
"when":"inuse"
}
},
{
"name" : "ohos.permission.PERMISSION2",
"reason": "$string:reason",
"usedScene": {
"abilities": [
"FormAbility"
],
"when":"always"
}
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
FA模型
使用FA模型的应用,需要在config.json配置文件中声明权限。
{
"module" : {
// ...
"reqPermissions":[
{
"name" : "ohos.permission.PERMISSION1",
"reason": "$string:reason",
"usedScene": {
"ability": [
"FormAbility"
],
"when":"inuse"
}
},
{
"name" : "ohos.permission.PERMISSION2",
"reason": "$string:reason",
"usedScene": {
"ability": [
"FormAbility"
],
"when":"always"
}
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ACL方式声明
当应用需要申请system_basic
和system_core
等级的权限时,比应用默认权限等级normal
更高。如果需要申请的权限等级高于应用默认的等级,需要使用ACL方式声明使用。
例如,如果应用需要访问用户公共目录中的音乐文件,需要申请ohos.permission.WRITE_AUDIO
权限,该权限属于system_basic
等级。如果应用需要截取屏幕图像,则需要申请ohos.permission.CAPTURE_SCREEN
权限,该权限属于system_core
等级。此时,需要将相关权限项配置到HarmonyAppProvision配置文件的acl
字段中。
{
// ...
"acls":{
"allowed-acls":[
"ohos.permission.WRITE_AUDIO",
"ohos.permission.CAPTURE_SCREEN"
]
}
}
2
3
4
5
6
7
8
9
向用户申请授权
当应用需要访问用户的隐私信息或使用系统能力时,例如获取位置信息、访问日历、使用相机拍摄照片或录制视频等,应该向用户请求授权。这需要使用 user_grant
类型权限。在此之前,应用需要进行权限校验,以判断当前调用者是否具备所需的权限。如果权限校验结果表明当前应用尚未被授权该权限,则应使用动态弹框授权方式,为用户提供手动授权的入口。示意效果如下图所示。
图1 向用户申请授权
说明:
每次访问受目标权限保护的接口之前,都需要使用 requestPermissionsFromUser() 接口请求相应的权限。用户可能在动态授予权限后通过系统设置来取消应用的权限,因此不能将之前授予的授权状态持久化。
Stage模型
以允许应用读取日历信息为例进行说明。
申请
ohos.permission.READ_CALENDAR
权限,配置方式请参见配置文件权限声明。校验当前是否已经授权。
在进行权限申请之前,需要先检查当前应用程序是否已经被授予了权限。可以通过调用checkAccessToken()方法来校验当前是否已经授权。如果已经授权,则可以直接访问目标操作,否则需要进行下一步操作,即向用户申请授权。
import bundleManager from '@ohos.bundle.bundleManager'; import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; async function checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> { let atManager = abilityAccessCtrl.createAtManager(); let grantStatus: abilityAccessCtrl.GrantStatus; // 获取应用程序的accessTokenID let tokenId: number; try { let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION); let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo; tokenId = appInfo.accessTokenId; } catch (err) { console.error(`getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}`); } // 校验应用是否被授予权限 try { grantStatus = await atManager.checkAccessToken(tokenId, permission); } catch (err) { console.error(`checkAccessToken failed, code is ${err.code}, message is ${err.message}`); } return grantStatus; } async function checkPermissions(): Promise<void> { const permissions: Array<Permissions> = ['ohos.permission.READ_CALENDAR']; let grantStatus: abilityAccessCtrl.GrantStatus = await checkAccessToken(permissions[0]); if (grantStatus === abilityAccessCtrl.GrantStatus.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
24
25
26
27
28
29
30
31
32
33
34
35
36
37动态向用户申请授权。
动态向用户申请权限是指在应用程序运行时向用户请求授权的过程。可以通过调用requestPermissionsFromUser()方法来实现。该方法接收一个权限列表参数,例如位置、日历、相机、麦克风等。用户可以选择授予权限或者拒绝授权。
可以在UIAbility的
onWindowStageCreate()
回调中调用requestPermissionsFromUser()方法来动态申请权限,也可以根据业务需要在UI中向用户申请授权。在UIAbility中向用户申请授权。
import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; const permissions: Array<Permissions> = ['ohos.permission.READ_CALENDAR']; export default class EntryAbility extends UIAbility { // ... onWindowStageCreate(windowStage: window.WindowStage) { // Main window is created, set main page for this ability let context = this.context; let atManager = abilityAccessCtrl.createAtManager(); // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗 atManager.requestPermissionsFromUser(context, permissions).then((data) => { let grantStatus: Array<number> = data.authResults; let length: number = grantStatus.length; for (let i = 0; i < length; i++) { if (grantStatus[i] === 0) { // 用户授权,可以继续访问目标操作 } else { // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 return; } } // 授权成功 }).catch((err) => { console.error(`requestPermissionsFromUser failed, code is ${err.code}, message is ${err.message}`); }) // ... } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34在UI中向用户申请授权。
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl'; import common from '@ohos.app.ability.common'; const permissions: Array<Permissions> = ['ohos.permission.READ_CALENDAR']; @Entry @Component struct Index { reqPermissionsFromUser(permissions: Array<Permissions>): void { let context = getContext(this) as common.UIAbilityContext; let atManager = abilityAccessCtrl.createAtManager(); // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗 atManager.requestPermissionsFromUser(context, permissions).then((data) => { let grantStatus: Array<number> = data.authResults; let length: number = grantStatus.length; for (let i = 0; i < length; i++) { if (grantStatus[i] === 0) { // 用户授权,可以继续访问目标操作 } else { // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 return; } } // 授权成功 }).catch((err) => { console.error(`requestPermissionsFromUser failed, code is ${err.code}, message is ${err.message}`); }) } // 页面展示 build() { // ... } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34处理授权结果。
调用requestPermissionsFromUser()方法后,应用程序将等待用户授权的结果。如果用户授权,则可以继续访问目标操作。如果用户拒绝授权,则需要提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限。
function openPermissionsInSystemSettings(): void { let context = getContext(this) as common.UIAbilityContext; let wantInfo = { action: 'action.settings.app.info', parameters: { settingsParamBundleName: 'com.example.myapplication' // 打开指定应用的详情页面 } } context.startAbility(wantInfo).then(() => { // ... }).catch((err) => { // ... }) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
FA模型
通过调用requestPermissionsFromUser()接口向用户动态申请授权。
import featureAbility from '@ohos.ability.featureAbility';
reqPermissions() {
let context = featureAbility.getContext();
let array:Array<string> = ["ohos.permission.PERMISSION2"];
//requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
context.requestPermissionsFromUser(array, 1).then(function(data) {
console.log("data:" + JSON.stringify(data));
console.log("data permissions:" + JSON.stringify(data.permissions));
console.log("data result:" + JSON.stringify(data.authResults));
}, (err) => {
console.error('Failed to start ability', err.code);
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
user_grant权限预授权
应用在申请user_grant
类型的权限默认未授权,需要通过拉起弹框由用户确认是否授予该权限。对于一些预制应用,不希望出现弹窗申请user_grant
类型的权限,例如系统相机应用需要使用麦克风ohos.permission.MICROPHONE
等权限,需要对麦克风等权限进行预授权,可以通过预授权的方式完成user_grant
类型权限的授权。预置配置文件在设备上的路径为/system/etc/app/install_list_permission.json
,设备开机启动时会读取该配置文件,在应用安装会对在文件中配置的user_grant
类型权限授权。预授权配置文件字段内容包括bundleName
、app_signature
和permissions
。
bundleName
字段配置为应用的Bundle名称。app_signature
字段配置为应用的指纹信息。指纹信息的配置参见应用特权配置指南。permissions
字段中name
配置为需要预授权的user_grant
类型的权限名;permissions
字段中userCancellable
表示为用户是否能够取消该预授权,配置为true,表示支持用户取消授权,为false则表示不支持用户取消授权。
说明:当前仅支持预置应用配置该文件。
[
// ...
{
"bundleName": "com.example.myapplication", // Bundle名称
"app_signature": ["****"], // 指纹信息
"permissions":[
{
"name": "ohos.permission.PERMISSION_X", // user_grant类型预授权的权限名
"userCancellable": false // 用户不可取消授权
},
{
"name": "ohos.permission.PERMISSION_Y", // user_grant类型预授权的权限名
"userCancellable": true // 用户可取消授权
}
]
}
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
相关实例
针对访问控制,有以下相关实例可供参考: