From 645f977552b1f93f93d764344a0570b084426e3f Mon Sep 17 00:00:00 2001 From: lsq Date: Sat, 26 Mar 2022 13:00:21 +0800 Subject: [PATCH] Signed-off-by: lsq Change-Id: I8cd57ad0a41da7a02b0f3651905b0900c4e207dd Change-Id: I9cf6fe5bfd65ec810324951407db23933d0734cd Signed-off-by: lsq --- .../apis/js-apis-abilityAccessCtrl.md | 2 + .../security/accesstoken-guidelines.md | 129 ++++++++- .../security/accesstoken-overview.md | 272 +++++++++++++++++- .../security/figures/figure1.png | Bin 0 -> 19146 bytes 4 files changed, 382 insertions(+), 21 deletions(-) create mode 100644 zh-cn/application-dev/security/figures/figure1.png diff --git a/zh-cn/application-dev/reference/apis/js-apis-abilityAccessCtrl.md b/zh-cn/application-dev/reference/apis/js-apis-abilityAccessCtrl.md index d5351e156e..7a29614e76 100644 --- a/zh-cn/application-dev/reference/apis/js-apis-abilityAccessCtrl.md +++ b/zh-cn/application-dev/reference/apis/js-apis-abilityAccessCtrl.md @@ -204,6 +204,8 @@ getPermissionFlags(tokenID: number, permissionName: string): Promise<number&g 获取指定应用的指定权限的flag,使用Promise方式异步返回结果。 +**需要权限:** ohos.permission.GET_SENSITIVE_PERMISSIONS or GRANT_SENSITIVE_PERMISSIONS or REVOKE_SENSITIVE_PERMISSIONS + **系统能力:** SystemCapability.Security.AccessToken **参数:** diff --git a/zh-cn/application-dev/security/accesstoken-guidelines.md b/zh-cn/application-dev/security/accesstoken-guidelines.md index 8186011789..84883ba8ee 100644 --- a/zh-cn/application-dev/security/accesstoken-guidelines.md +++ b/zh-cn/application-dev/security/accesstoken-guidelines.md @@ -2,22 +2,127 @@ ## 场景介绍 -当应用申请的权限需要用户授权,即申请的权限为user_grant权限时,可以通过权限校验,判断当前调用者是否具备相应权限。 +以下示例代码基于此场景假设:应用因为应用核心功能诉求,需要申请权限"ohos.permission.PERMISSION1"和权限"ohos.permission.PERMISSION2"。 +- 应用的APL等级为normal。 +- 权限"ohos.permission.PERMISSION1"的权限等级为normal,权限类型为system_grant。 +- 权限"ohos.permission.PERMISSION2"的权限等级为system_basic, 权限类型为user_grant。 + +> **注意事项:** +> +> 当前场景下,应用申请的权限包括了user_grant权限,对这部分user_grant权限,可以先通过权限校验,判断当前调用者是否具备相应权限。 +> +> 当权限校验结果显示当前应用尚未被授权该权限时,再通过动态弹框授权方式给用户提供手动授权入口。 +> ## 接口说明 -接口的具体说明可以查阅[API参考](../reference/apis/js-apis-abilityAccessCtrl.md) -| 接口名 | 描述 | -| ------------------------------------------------------------ | ---------------- | + +以下仅列举本指导使用的接口,更多说明可以查阅[API参考](../reference/apis/js-apis-abilityAccessCtrl.md)。 + +| 接口名 | 描述 | +| ------------------------------------------------------------ | --------------------------------------------------- | | verifyAccessToken(tokenID: number, permissionName: string): Promise<GrantStatus> | 校验应用是否授予权限,使用Promise方式异步返回结果。 | -## 开发步骤 -对访问者进行权限校验的开发步骤为: +## 权限申请声明 + +### config.json文件声明 + +应用需要在config.json文件中对需要的权限逐个进行声明。没有在config.json中声明的权限,应用无法获得此应用授权。 + +**config.json标签说明:** + +| 标签 | 说明 | +| --------- | ------------------------------------------------------------ | +| name | 权限名称。 | +| reason | 当申请的权限为user_grant权限时,此字段必填,描述申请权限的原因。 | +| usedScene | 当申请的权限为user_grant权限时,此字段必填,描述权限使用的场景和时机。 | +| abilities | 标识需要使用到该权限的元能力,标签为数组形式。 | +| when | 标识权限使用的时机,值为"inuse/always",表示为仅允许前台使用和前后台都可使用。 | + +**示例:** + +```json +{ + "module" : { + "requesetPermissions":[ + { + "name" : "ohos.permission.PERMISSION1", + "reason": "$string:reason", + "usedScene": { + "abilities": [ + "FormAbility" + ], + "when":"inuse" + } + }, + { + "name" : "ohos.permission.PERMISSION2", + "reason": "$string:reason", + "usedScene": { + "abilities": [ + "FormAbility" + ], + "when":"always" + } + } + ], + } +} +``` +## ACL方式声明 + +如上述示例所示,权限"ohos.permission.PERMISSION2"的权限等级为system_basic,高于应用此时应用的APL等级,用户的最佳做法是使用ACL方式。 + +**在config.json文件声明的基础上**,应用还需要在profile文件中声明不满足申请条件部分的权限。该场景中,用户应该在字段"acls"中做声明如下: +```json +{ + "version-name": "1.0.0", + "version-code": 1, + "app-distribution-type": "os_integration", + "uuid": "5027b99e-5f9e-465d-9508-a9e0134ffe18", + "validity": { + "not-before": 1594865258, + "not-after": 1689473258 + }, + "type": "release", + "bundle-info": { + "developer-id": "OpenHarmony", + "distribution-certificate": "-----BEGIN CERTIFICATE-----\nMIICMzCCAbegAwIBAgIEaOC/zDAMBggqhkjOPQQDAwUAMGMxCzAJBgNVBAYTAkNO\nMRQwEgYDVQQKEwtPcGVuSGFybW9ueTEZMBcGA1UECxMQT3Blbkhhcm1vbnkgVGVh\nbTEjMCEGA1UEAxMaT3Blbkhhcm1vbnkgQXBwbGljYXRpb24gQ0EwHhcNMjEwMjAy\nMTIxOTMxWhcNNDkxMjMxMTIxOTMxWjBoMQswCQYDVQQGEwJDTjEUMBIGA1UEChML\nT3Blbkhhcm1vbnkxGTAXBgNVBAsTEE9wZW5IYXJtb255IFRlYW0xKDAmBgNVBAMT\nH09wZW5IYXJtb255IEFwcGxpY2F0aW9uIFJlbGVhc2UwWTATBgcqhkjOPQIBBggq\nhkjOPQMBBwNCAATbYOCQQpW5fdkYHN45v0X3AHax12jPBdEDosFRIZ1eXmxOYzSG\nJwMfsHhUU90E8lI0TXYZnNmgM1sovubeQqATo1IwUDAfBgNVHSMEGDAWgBTbhrci\nFtULoUu33SV7ufEFfaItRzAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFPtxruhl\ncRBQsJdwcZqLu9oNUVgaMAwGCCqGSM49BAMDBQADaAAwZQIxAJta0PQ2p4DIu/ps\nLMdLCDgQ5UH1l0B4PGhBlMgdi2zf8nk9spazEQI/0XNwpft8QAIwHSuA2WelVi/o\nzAlF08DnbJrOOtOnQq5wHOPlDYB4OtUzOYJk9scotrEnJxJzGsh/\n-----END CERTIFICATE-----\n", + "bundle-name": "com.ohos.permissionmanager", + "apl": "system_core", + "app-feature": "hos_system_app" + }, + "acls": { + "allowed-acls": [ + "ohos.permission.PERMISSION2" + ] + }, + "permissions": { + "restricted-permissions": [] + }, + "issuer": "pki_internal" +} +``` + +## 申请授权user_grant权限 + +在前期的权限声明步骤后,在安装过程中系统会对system_grant类型的权限进行权限预授权,而user_grant类型权限则需要用户进行手动授权。 -1. 获取调用者的身份标识: tokenId -2. 识别需要校验的权限: permissionNameUser -3. 对当前调用者进行权限校验 +所以,应用在调用受"ohos.permission.PERMISSION2"权限保护的接口前,需要先校验应用是否已经获取该权限。 + +如果校验结果显示,应用已经获取了该权限,那么应用可以直接访问该目标接口,否则,应用需要通过动态弹框先申请用户授权,并根据授权结果进行相应处理,处理方式可参考[访问控制开发概述](accesstoken-overview.md)。 + +> **注意事项:** +> +> 不能把之前授予的状态持久化,每次访问受目标权限保护的接口前,都应该检查权限授权状态,因为用户在动态授予后可能通过设置取消应用的权限。 + +## 完整示例 + +对访问者进行权限校验的开发步骤为: -代码示例如下: +1. 获取调用者的身份标识:tokenId。 +2. 识别需要校验的权限:permissionNameUser。 +3. 对访问verifyAccessToken接口对当前调用者进行权限校验。 +4. 根据权限校验结果采取对应的措施。 ```js import {describe, beforeEach, afterEach, it, expect} from 'deccjsunit/index' @@ -25,7 +130,7 @@ import bundle from '@ohos.bundle' async requestPermission() { - var permissionNameUser = "ohos.permission.ALPHA"; + var permissionNameUser = "ohos.permission.PERMISSION2"; var bundleFlag = 0; var tokenID = undefined; var userID = 100; @@ -44,4 +149,4 @@ ``` > **说明:** -动态授权申请接口的使用详见[API参考](../reference/apis/js-apis-ability-context.md) \ No newline at end of file +> 动态授权申请接口的使用详见[API参考](../reference/apis/js-apis-ability-context.md)。 diff --git a/zh-cn/application-dev/security/accesstoken-overview.md b/zh-cn/application-dev/security/accesstoken-overview.md index 1fef21e91a..53e1626d32 100644 --- a/zh-cn/application-dev/security/accesstoken-overview.md +++ b/zh-cn/application-dev/security/accesstoken-overview.md @@ -1,18 +1,272 @@ -# 访问控制开发指南 +# 访问控制开发概述 -## 功能简介 +## 简介 ATM(AccessTokenManager)是OpenHarmony上基于AccessToken构建的统一的应用权限管理能力。 -当前,ATM模块对应用提供了权限校验功能,应用可以检查当前访问者是否具有所需的权限。 +默认情况下,应用只能访问有限的系统资源。但某些情况下,应用为了扩展功能的诉求,需要访问额外的系统或其他应用的数据(包括用户个人数据)、功能。系统或应用也必须以明确的方式对外提供接口来共享其数据或功能。OpenHarmony提供了一种访问控制机制来保证这些数据或功能不会被不当或恶意使用,即应用权限。 +应用权限保护的对象可以分为数据和功能: -## 基本概念 +- 数据包含了个人数据(如照片、通讯录、日历、位置等)、设备数据(如设备标识、相机、麦克风等)、应用数据。 +- 功能则包括了设备功能(如打电话、发短信、联网等)、应用功能(如弹出悬浮框、创建快捷方式等)等。 -当前,ATM提供的应用权限校验功能是基于统一管理的TokenID(Token identity)。 +应用权限是程序访问操作某种对象的通行证。权限在应用层面要求有明确定义,应用权限使得系统可以规范各类应用程序的行为准则,实现用户隐私的保护机制。当应用访问操作目标对象时,目标对象会对应用进行权限检查,如果没有对应权限,则访问操作将被拒绝。 -- TokenID:32bits的设备内唯一标识符,用于标识每个应用的Accestoken信息。 -- Accestoken信息:主要包括应用身份标识APPID、用户ID、应用分身索引、应用APL(Ability Privilege Level)、应用权限信息等。 +当前,ATM提供的应用权限校验功能是基于统一管理的TokenID(Token identity)。TokenID是每个应用的身份标识,ATM通过应用的TokenID来管理应用的权限。 -## 约束与限制 +## 权限的工作流程 - - 应用不允许自定义权限,系统权限定义信息详见[权限定义信息](https://gitee.com/openharmony/resources/blob/master/systemres/main/config.json) \ No newline at end of file +应用在访问数据或者执行操作时,需要评估该行为是否需要应用具备相关的权限。如果确认需要目标权限,则需要在应用安装包中申请目标权限。 + +然后,需要判断目标权限是否属于用户授权类。如果是,应用需要使用动态授权弹框来提供用户授权界面,请求用户授权目标权限。 + +当用户授予应用所需权限后,应用可成功访问目标数据或执行目标操作。 + +应用使用权限的工作流程如图所示。 + +![](figures/figure1.png) + +## 权限使用场景说明 + +### 场景示例 + +下面列举两种应用需要使用权限的常见场景,用作参考。 + +- **视频播放类应用** + + 视频播放类应用要使用多媒体功能,应用必须对用户外部存储的媒体文件信息进行读取和写入,所以应用需要至少申请以下两个权限: + + (1) ohos.permission.READ_MEDIA 允许应用读取用户外部存储中的媒体文件信息。 + + (2) ohos.permission.WRITE_MEDIA 允许应用读写用户外部存储中的媒体文件信息。 + +- **摄影美图类应用** + + 摄影美图类应用需要使用到相机功能,那么应用访问相机服务前,需要申请到相机权限: + + (1) ohos.permission.CAMERA 允许应用使用相机拍摄照片和录制视频。 + +### 基本原则 + +在进行权限的申请和使用时,需要满足以下以下基本原则: + +- 应用申请的权限,都必须有明确、合理的使用场景和功能说明,确保用户能够清晰明了地知道申请权限的目的、场景、用途;禁止诱导、误导用户授权;应用使用权限必须与申请所述一致。 +- 应用权限申请遵循最小化原则,只申请业务功能所必要的权限,禁止申请不必要的权限。 +- 应用在首次启动时,避免频繁弹窗申请多个权限;权限须在用户使用对应业务功能时动态申请。 +- 用户拒绝授予某个权限时,与此权限无关的其他业务功能应能正常使用,不能影响应用的正常注册或登录。 +- 业务功能所需要的权限被用户拒绝且禁止后不再提示,当用户主动触发使用此业务功能或为实现业务功能所必须时,应用程序可通过界面内文字引导,让用户主动到“系统设置”中授权。 + +- 当前不允许应用自行定义权限,应用申请的权限应该从已有的权限列表中选择。 + +## 权限等级说明 + +根据接口所涉数据的敏感程度或所涉能力的安全威胁影响,ATM模块定义了不同开放范围的权限等级来保护用户隐私。 + +### 应用APL等级说明 + +元能力权限等级APL(Ability Privilege Level)指的是应用的权限申请优先级的定义,不同APL等级的应用能够申请的权限等级不同。 + +应用的等级可以分为三个等级,分别是: + +| APL级别 | 说明 | +| ---------------- | -------------------------------------- | +| system_core等级 | 该等级的应用服务提供操作系统核心能力。 | +| system_basic等级 | 该等级的应用服务提供系统基础服务。 | +| normal等级 | 普通应用。 | + +默认情况下,应用的APL等级都为normal等级,如果应用需要将自身的APL等级声明为system_basic及以上的APL等级,需要进行以下步骤: +- 申请应用市场审核并通过。 +- 开发应用安装包时,需要修改应用的profile文件,在文件的"apl"字段声明应用的APL等级,并使用profile签名工具生成证书。具体签名流程可以查看页面[配置OpenHarmony应用签名信息](../quick-start/configuring-openharmony-app-signature.md)。 + +### 权限等级说明 + +根据权限对于不同等级应用有不同的开放范围,权限类型对应分为以下三种,等级依次提高。 + +- **normal权限** + + normal 权限允许应用访问超出默认规则外的普通系统资源。这些系统资源的开放(包括数据和功能)对用户隐私以及其他应用带来的风险很小。 + + 该类型的权限仅向APL等级为normal及以上的应用开放。 + +- **system_basic权限** + + system_basic权限允许应用访问操作系统基础服务相关的资源。这部分系统基础服务属于系统提供或者预置的基础功能,比如系统设置、身份认证等。这些系统资源的开放对用户隐私以及其他应用带来的风险较大。 + + 该类型的权限仅向APL等级为system_basic等级的应用开放。 + +- **system_core权限** + + system_core权限涉及到开放操作系统核心资源的访问操作。这部分系统资源是系统最核心的底层服务,如果遭受破坏,操作系统将无法正常运行。 + + 鉴于该类型权限对系统的影响程度非常大,目前暂不向任何应用开放。 + +### 访问控制列表(ACL)说明 + +如上所述,权限等级和应用的APL等级是一一对应的。原则上,**拥有低APL等级的应用默认无法申请更高等级的权限**。 + +访问控制列表ACL(Access Control List)提供了解决低等级应用访问高等级权限问题的特殊渠道。 + +**场景举例:** + +开发者正在开发应用A,该应用的APL等级为normal级别。由于功能场景需要,应用A必须申请到权限B和权限C,其中,权限B的权限等级为system_basic,权限C的权限等级为normal级别。此时,推荐开发者使用ACL方式来申请权限B。 + +ACL方式的工作流程可以参考[ACL方式使用说明](#ACL方式使用说明)。 + +## 权限类型说明 + +根据授权方式的不同,权限类型可分为system_grant(系统授权)和user_grant(用户授权)。 + +- **system_grant** + + system_grant指的是系统授权类型,在该类型的权限许可下,应用被允许访问的数据不会涉及到用户或设备的敏感信息,应用被允许执行的操作不会对系统或者其他应用产生大的不利影响。 + + 如果在应用中申请了system_grant权限,那么系统会在用户安装应用时,自动把相应权限授予给应用。应用需要在应用商店的详情页面,向用户展示所申请的system_grant权限列表。 + +- **user_grant** + + user_grant指的是用户授权类型,在该类型的权限许可下,应用被允许访问的数据将会涉及到用户或设备的敏感信息,应用被允许执行的操作可能对系统或者其他应用产生严重的影响。 + + 该类型权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。 + + 比如说,在[权限定义列表](#权限定义列表)中,麦克风和摄像头对应的权限都是属于用户授权权限,列表中给出了详细的权限使用理由。 + + 应用需要在应用商店的详情页面,向用户展示所申请的user_grant权限列表。 + +## 不同权限类型的授权流程 + +如[权限的工作流程](#权限的工作流程)所示,如果应用需要获取目标权限,那么需要先进行权限申请。 + +应用获取权限的流程取决于相应的权限类型: + +- 如果目标权限是system_grant类型,开发者需要在config.json文件中[声明目标权限](accesstoken-guidelines.md),系统会在安装应用时为其进行权限预授予。 + +- 如果目标权限是user_grant类型,开发者需要先在config.json文件中[声明目标权限](accesstoken-guidelines.md),然后运行时发送弹窗,请求用户授权。 + +### user_grant权限请求授权的步骤详解 + +在应用需要获取user_grant权限时,请完成以下步骤: + +1. 在config.json文件中,声明应用需要请求的权限,详见[访问控制开发指导](accesstoken-guidelines.md)。 + +2. 将应用中需要申请权限的目标对象与对应目标权限进行关联,让用户明确地知道,哪些操作需要用户向应用授予指定的权限。 + +3. 运行应用时,需要检查当前用户是否以及授权应用所需的权限,如果已授权,那么应用可以直接访问操作目标对象。如果当前用户尚未授予应用所需的权限,在用户触发访问操作目标对象时精准触发动态授权弹框。 + +4. 检查用户的授权结果。确认用户已授权才可以进行下一步操作。 + +**注意事项:** + +- 每次执行需要目标权限的操作时,应用都必须检查自己是否已经具有该权限。 + +- 如需检查用户是否已向您的应用授予特定权限,可以使用[verifyAccessToken](../reference/apis/js-apis-abilityAccessCtrl.md)函数,此方法会返回 [PERMISSION_GRANTED](../reference/apis/js-apis-abilityAccessCtrl.md)或[PERMISSION_DENIED](../reference/apis/js-apis-abilityAccessCtrl.md)。具体的示例代码可以查看[访问控制开发指导](#accesstoken-guidelines.md)。 +- user_grant权限授权要基于用户可知可控的原则,需要应用在运行时主动调用系统动态申请权限的接口,系统弹框由用户授权,用户结合应用运行场景的上下文,识别出应用申请相应敏感权限的合理性,从而做出正确的选择。 +- 即使用户向应用授予过请求的权限,应用在调用受此权限管控的接口前,也应该先检查自己有无此权限,而不能把之前授予的状态持久化,因为用户在动态授予后还可以通过设置取消应用的权限。 + +### ACL方式使用说明 + +如果应用申请的权限中,存在部分权限的权限等级比应用APL等级高,开发者可以选择通过ACL方式来解决这个等级不匹配的问题。 + +在上述的[授权流程](# 不同权限类型的授权流程)的基础上,应用需要进行额外的ACL声明步骤。 + +应用除了需要在config.json文件声明所需申请的权限,还需要在应用的[profile文件中声明](accesstoken-guidelines.md)不满足申请条件的高等级权限,接下来的授权流程不变。 + +**ACL申请方式须知** + +* 申请应用市场审核并通过。 +* 开发应用安装包时,需要修改应用的profile文件,在文件的"acl"字段声明目标的访问控制列表,并使用profile签名工具生成证书。具体签名流程可以查看页面[配置OpenHarmony应用签名信息](../quick-start/configuring-openharmony-app-signature.md)。 + +## 权限定义列表 + +以下给出当前系统定义的权限信息列表。 + +| 权限名 | 权限级别 | 授权方式 | ACL使能 | 权限说明 | +| -------------------------------------------------------- | ------------ | ------------ | ------- | ------------------------------------------------------------ | +| ohos.permission.USE_BLUETOOTH | normal | system_grant | TRUE | 允许应用查看蓝牙的配置。 | +| ohos.permission.DISCOVER_BLUETOOTH | normal | system_grant | TRUE | 允许应用配置本地蓝牙,查找远端设备且与之配对连接。 | +| ohos.permission.MANAGE_BLUETOOTH | system_basic | system_grant | TRUE | 允许应用配对蓝牙设备,并对设备的电话簿或消息进行访问。 | +| ohos.permission.INTERNET | normal | system_grant | TRUE | 允许使用Internet网络。 | +| ohos.permission.MODIFY_AUDIO_SETTINGS | normal | system_grant | TRUE | 允许应用修改音频设置。 | +| ohos.permission.GET_TELEPHONY_STATE | system_basic | system_grant | TRUE | 允许应用读取电话信息。 | +| ohos.permission.REQUIRE_FORM | system_basic | system_grant | TRUE | 允许应用获取Ability Form。 | +| ohos.permission.GET_NETWORK_INFO | normal | system_grant | TRUE | 允许应用获取数据网络信息。 | +| ohos.permission.PLACE_CALL | system_basic | system_grant | TRUE | 允许应用直接拨打电话。 | +| ohos.permission.SET_NETWORK_INFO | normal | system_grant | TRUE | 允许应用配置数据网络。 | +| ohos.permission.REMOVE_CACHE_FILES | system_basic | system_grant | TRUE | 允许清理指定应用的缓存。 | +| ohos.permission.REBOOT | system_basic | system_grant | TRUE | 允许应用重启设备。 | +| ohos.permission.RUNNING_LOCK | normal | system_grant | TRUE | 允许应用获取运行锁,保证应用在后台的持续运行。 | +| ohos.permission.ENROLL_BIOMETRIC | system_core | system_grant | FALSE | 允许应用录入或删除生物特征数据。 | +| ohos.permission.ACCESS_BIOMETRIC | normal | system_grant | FALSE | 允许应用使用生物特征识别能力进行身份认证。 | +| ohos.permission.ACCESS_BIOMETRIC_INTERNAL | system_core | system_grant | FALSE | 允许应用申请或释放生物特征识别的资源。 | +| ohos.permission.RESET_BIOMETRIC_LOCKOUT | system_core | system_grant | FALSE | 允许应用重置生物特征识别的认证失败计数。 | +| ohos.permission.SET_TIME | system_basic | system_grant | TRUE | 允许应用修改系统时间。 | +| ohos.permission.SET_TIME_ZONE | system_basic | system_grant | TRUE | 允许应用修改系统时区。 | +| ohos.permission.DOWNLOAD_SESSION_MANAGER | system_core | system_grant | TRUE | 允许应用管理下载任务会话。 | +| ohos.permission.COMMONEVENT_STICKY | normal | system_grant | TRUE | 允许应用发布粘性公共事件。 | +| ohos.permission.SYSTEM_FLOAT_WINDOW | normal | system_grant | TRUE | 允许应用使用悬浮窗的能力。 | +| ohos.permission.POWER_MANAGER | system_core | system_grant | TRUE | 允许应用调用电源管理子系统的接口,休眠或者唤醒设备。 | +| ohos.permission.REFRESH_USER_ACTION | system_basic | system_grant | TRUE | 允许应用在收到用户事件时,重新计算超时时间。 | +| ohos.permission.POWER_OPTIMIZATION | system_basic | system_grant | TRUE | 允许系统应用设置省电模式、获取省电模式的配置信息并接收配置变化的通知。 | +| ohos.permission.REBOOT_RECOVERY | system_basic | system_grant | TRUE | 允许系统应用重启设备并进入恢复模式。 | +| ohos.permission.MANAGE_LOCAL_ACCOUNTS | system_basic | system_grant | TRUE | 允许应用管理本地用户账号。 | +| ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS | system_basic | system_grant | TRUE | 允许多个系统账号之间相互访问。 | +| ohos.permission.VIBRATE | normal | system_grant | TRUE | 允许应用控制马达振动。 | +| ohos.permission.CONNECT_IME_ABILITY | system_core | system_grant | TRUE | 允许绑定输入法Ability(InputMethodAbility)。 | +| ohos.permission.CONNECT_SCREEN_SAVER_ABILITY | system_core | system_grant | TRUE | 允许绑定屏保Ability(ScreenSaverAbility)。 | +| ohos.permission.READ_SCREEN_SAVER | system_basic | system_grant | TRUE | 允许应用查询屏保状态信息。 | +| ohos.permission.WRITE_SCREEN_SAVER | system_basic | system_grant | TRUE | 允许应用修改屏保状态信息。 | +| ohos.permission.SET_WALLPAPER | normal | system_grant | TRUE | 允许应用设置静态壁纸。 | +| ohos.permission.GET_WALLPAPER | system_basic | system_grant | TRUE | 允许应用读取壁纸文件。 | +| ohos.permission.CHANGE_ABILITY_ENABLED_STATE | system_basic | system_grant | TRUE | 允许改变应用或者组件的使能状态。 | +| ohos.permission.ACCESS_MISSIONS | system_basic | system_grant | TRUE | 允许应用访问任务栈信息。 | +| ohos.permission.CLEAN_BACKGROUND_PROCESSES | normal | system_grant | TRUE | 允许应用根据包名清理相关后台进程。 | +| ohos.permission.KEEP_BACKGROUND_RUNNING | normal | system_grant | TRUE | 允许Service Ability在后台持续运行。 | +| ohos.permission.UPDATE_CONFIGURATION | system_basic | system_grant | TRUE | 允许更新系统配置。 | +| ohos.permission.GRANT_SENSITIVE_PERMISSIONS | system_core | system_grant | TRUE | 允许应用为其他应用授予敏感权限。 | +| ohos.permission.REVOKE_SENSITIVE_PERMISSIONS | system_core | system_grant | TRUE | 允许应用撤销给其他应用授予的敏感信息。 | +| ohos.permission.GET_SENSITIVE_PERMISSIONS | system_core | system_grant | TRUE | 允许应用读取其他应用的敏感权限的状态。 | +| ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS_EXTENSION | system_core | system_grant | TRUE | 允许应用跨用户对其他应用的属性进行设置。 | +| ohos.permission.LISTEN_BUNDLE_CHANGE | system_basic | system_grant | TRUE | 允许应用监听其他应用安装、更新、卸载状态的变化。 | +| ohos.permission.GET_BUNDLE_INFO | normal | system_grant | TRUE | 允许应用查询其他应用的信息。 | +| ohos.permission.ACCELEROMETER | normal | system_grant | TRUE | 允许应用读取加速度传感器的数据。 | +| ohos.permission.GYROSCOPE | normal | system_grant | TRUE | 允许应用读取陀螺仪传感器的数据。 | +| ohos.permission.GET_BUNDLE_INFO_PRIVILEGED | system_basic | system_grant | TRUE | 允许应用查询其他应用的信息。 | +| ohos.permission.INSTALL_BUNDLE | system_core | system_grant | TRUE | 允许应用安装、卸载其他应用。 | +| ohos.permission.MANAGE_SHORTCUTS | system_core | system_grant | TRUE | 允许应用查询其他应用的快捷方式信息、启动其他应用的快捷方式。 | +| ohos.permission.radio.ACCESS_FM_AM | system_core | system_grant | TRUE | 允许应用获取收音机相关服务。 | +| ohos.permission.SET_TELEPHONY_STATE | system_basic | system_grant | TRUE | 允许应用修改telephone的状态。 | +| ohos.permission.START_ABILIIES_FROM_BACKGROUND | system_basic | system_grant | TRUE | 允许应用在后台启动FA。 | +| ohos.permission.BUNDLE_ACTIVE_INFO | system_basic | system_grant | TRUE | 允许系统应用查询其他应用在前台或后台的运行时间。 | +| ohos.permission.START_INVISIBLE_ABILITY | system_core | system_grant | TRUE | 无论Ability是否可见,都允许应用进行调用。 | +| ohos.permission.sec.ACCESS_UDID | system_basic | system_grant | TRUE | 允许系统应用获取UDID | +| ohos.permission.LAUNCH_DATA_PRIVACY_CENTER | system_basic | system_grant | TRUE | 允许应用从其隐私声明页面跳转至"数据与隐私"页面。 | +| ohos.permission.MANAGE_MEDIA_RESOURCES | system_basic | system_grant | TRUE | 允许应用程序获取当前设备正在播放的媒体资源,并对其进行管理。 | +| ohos.permission.PUBLISH_AGENT_REMINDER | normal | system_grant | TRUE | 允许该应用使用后台代理提醒。 | +| ohos.permission.CONTROL_TASK_SYNC_ANIMATOR | system_core | system_grant | TRUE | 允许应用使用同步任务动画。 | +| ohos.permission.INPUT_MONITORING | system_core | system_grant | TRUE | 允许应用监听输入事件,仅系统签名应用可申请此权限。 | +| ohos.permission.MANAGE_MISSIONS | system_core | system_grant | TRUE | 允许用户管理元能力任务栈。 | +| ohos.permission.NOTIFICATION_CONTROLLER | system_core | system_grant | TRUE | 允许应用管理通知和订阅通知。当前仅支持系统应用申请该权限。 | +| ohos.permission.CONNECTIVITY_INTERNAL | system_basic | system_grant | TRUE | 允许应用程序获取网络相关的信息或修改网络相关设置。当前仅支持系统应用申请该权限。 | +| ohos.permission.ANSWER_CALL | system_basic | user_grant | TRUE | 允许应用接听来电。 | +| ohos.permission.READ_CALENDAR | normal | user_grant | TRUE | 允许应用读取日历信息。 | +| ohos.permission.READ_CALL_LOG | system_basic | user_grant | TRUE | 允许应用读取通话记录。 | +| ohos.permission.READ_CELL_MESSAGES | system_basic | user_grant | TRUE | 允许应用读取设备收到的小区广播信息。 | +| ohos.permission.READ_CONTACTS | system_basic | user_grant | TRUE | 允许应用读取联系人数据。 | +| ohos.permission.READ_MESSAGES | system_basic | user_grant | TRUE | 允许应用读取短信息。 | +| ohos.permission.RECEIVE_MMS | system_basic | user_grant | TRUE | 允许应用接收和处理彩信。 | +| ohos.permission.RECEIVE_SMS | system_basic | user_grant | TRUE | 允许应用接收和处理短信。 | +| ohos.permission.RECEIVE_WAP_MESSAGES | system_basic | user_grant | TRUE | 允许应用接收和处理WAP消息。 | +| ohos.permission.MICROPHONE | normal | user_grant | TRUE | 允许应用使用麦克风。 | +| ohos.permission.SEND_MESSAGES | system_basic | user_grant | TRUE | 允许应用发送短信。 | +| ohos.permission.WRITE_CALENDAR | normal | user_grant | TRUE | 允许应用添加、移除或更改日历活动。 | +| ohos.permission.WRITE_CALL_LOG | system_basic | user_grant | TRUE | 允许应用添加、移除或更改通话记录。 | +| ohos.permission.WRITE_CONTACTS | system_basic | user_grant | TRUE | 允许应用添加、移除或更改联系人数据。 | +| ohos.permission.DISTRIBUTED_DATASYNC | normal | user_grant | TRUE | 允许不同设备间的数据交换。 | +| ohos.permission.MANAGE_VOICEMAIL | system_basic | user_grant | TRUE | 允许应用在语音信箱中留言 | +| ohos.permission.LOCATION_IN_BACKGROUND | normal | user_grant | FALSE | 允许应用在后台运行时获取设备位置信息。 | +| ohos.permission.LOCATION | normal | user_grant | TRUE | 允许应用获取设备位置信息。 | +| ohos.permission.MEDIA_LOCATION | normal | user_grant | TRUE | 允许应用访问用户媒体文件中的地理位置信息。 | +| ohos.permission.CAMERA | normal | user_grant | TRUE | 允许应用使用相机拍摄照片和录制视频。 | +| ohos.permission.READ_MEDIA | normal | user_grant | TRUE | 允许应用读取用户外部存储中的媒体文件信息。 | +| ohos.permission.WRITE_MEDIA | normal | user_grant | TRUE | 允许应用读写用户外部存储中的媒体文件信息。 | +| ohos.permission.ACTIVITY_MOTION | normal | user_grant | TRUE | 允许应用读取用户当前的运动状态。 | +| ohos.permission.READ_HEALTH_DATA | normal | user_grant | TRUE | 允许应用读取用户的健康数据。 | diff --git a/zh-cn/application-dev/security/figures/figure1.png b/zh-cn/application-dev/security/figures/figure1.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c57888cc065ddb5239600ae7f44e6585237804 GIT binary patch literal 19146 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�%_^|z~wSIX7fn#P;TMTQsn=D^>JcX0O@&$JF(YQ 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 literal 0 HcmV?d00001 -- GitLab