基本概念
应用沙盒
系统利用内核保护机制来识别和隔离应用资源,可将不同的应用隔离开,保护应用自身和系统免受恶意应用的攻击。默认情况下,应用间不能彼此交互,而且对系统的访问会受到限制。例如,如果应用A(一个单独的应用)尝试在没有权限的情况下读取应用B的数据或者调用系统的能力拨打电话,操作系统会阻止此类行为,因为应用 A 没有被授予相应的权限。
应用权限
由于系统通过沙盒机制管理各个应用,在默认规则下,应用只能访问有限的系统资源。但应用为了扩展功能的需要,需要访问自身沙盒之外的系统或其他应用的数据(包括用户个人数据)或能力;系统或应用也必须以明确的方式对外提供接口来共享其数据或能力。为了保证这些数据或能力不会被不当或恶意使用,就需要有一种访问控制机制来保护,这就是应用权限。
应用权限是程序访问操作某种对象的许可。权限在应用层面要求明确定义且经用户授权,以便系统化地规范各类应用程序的行为准则与权限许可。
权限保护的对象
权限保护的对象可以分为数据和能力。数据包含了个人数据(如照片、通讯录、日历、位置等)、设备数据(如设备标识、相机、麦克风等)、应用数据;能力包括了设备能力(如打电话、发短信、联网等)、应用能力(如弹出悬浮框、创建快捷方式等)等。
权限开放范围
权限开放范围指一个权限能被哪些应用申请。按可信程度从高到低的顺序,不同权限开放范围对应的应用可分为:系统服务、系统应用、系统预置特权应用、同签名应用、系统预置普通应用、持有权限证书的后装应用、其他普通应用,开放范围依次扩大。
敏感权限
涉及访问个人数据(如:照片、通讯录、日历、本机号码、短信等)和操作敏感能力(如:相机、麦克风等)的权限。
应用核心功能
一个应用可能提供了多种功能,其中应用为满足用户的关键需求而提供的功能,称为应用的核心功能。这是一个相对宽泛的概念,本规范用来辅助描述用户权限授权的预期。用户选择安装一个应用,通常是被应用的核心功能所吸引。比如导航类应用,定位导航就是这种应用的核心功能;比如媒体类应用,播放以及媒体资源管理就是核心功能,这些功能所需要的权限,用户在安装时内心已经倾向于授予(否则就不会去安装)。与核心功能相对应的是辅助功能,这些功能所需要的权限,需要向用户清晰说明目的、场景等信息,由用户授权。既不属于核心功能,也不是支撑核心功能的辅助功能,就是多余功能。不少应用存在并非为用户服务的功能,这些功能所需要的权限通常被用户禁止。
最小必要权限
保障应用某一服务类型正常运行所需要的应用权限的最小集,一旦缺少将导致该类型服务无法实现或无法正常运行的应用权限。
运作机制
系统所有应用均在应用沙盒内运行。默认情况下,应用只能访问有限的系统资源,系统负责管理应用对资源的访问权限。这些限制是通过DAC(Discretionary Access Control)、MAC(Mandatory Access Control)以及本文描述的应用权限机制等多种不同的形式实现的。因应用需要实现其某些功能而必须访问系统或其他应用的数据或操作某些器件,此时就需要系统或其他应用能提供接口,考虑到安全,就需要对这些接口采用一种限制措施,这就是称为“应用权限”的安全机制。
接口的提供涉及到其权限的命名和分组、对外开放的范围、被授予的应用、以及用户的参与和体验。应用权限管理模块的目的就是负责管理由接口提供方(访问客体)、接口使用方(访问主体)、系统(包括云侧和端侧)和用户等共同参与的整个流程,保证受限接口是在约定好的规则下被正常使用,避免接口被滥用而导致用户、应用和设备受损。
权限声明
应用需要在config.json中使用“reqPermissions”属性对需要的权限逐个进行声明。
若使用到的三方库也涉及权限使用,也需统一在应用的config.json中逐个声明。
没有在config.json中声明的权限,应用就无法获得此权限的授权。
动态申请敏感权限
动态申请敏感权限基于用户可知可控的原则,需要应用在运行时主动调用系统动态申请权限的接口,系统弹框由用户授权,用户结合应用运行场景的上下文,识别出应用申请相应敏感权限的合理性,从而做出正确的选择。
即使用户向应用授予了请求的权限,应用在调用受此权限管控的接口前,也应该先检查自己有无此权限,而不能把之前授予的状态持久化,因为用户在动态授予后还可以通过设置取消应用的权限。
自定义权限
HarmonyOS为了保证应用对外提供的接口不被恶意调用,需要对调用接口的调用者进行鉴权。
大多情况下,系统已定义的权限满足了应用的基本需要,若有特殊的访问控制需要,应用可在config.json中以"defPermissions": []属性来定义新的权限,并通过“availableScope”和“grantMode”两个属性分别确定权限的开放范围和授权方式,使得权限定义更加灵活且易于理解。
为了避免应用自定义新权限出现重名的情况,建议应用对新权限的命名以包名的前两个字段开头,这样可以防止不同开发者的应用间出现自定义权限重名的情况。
权限保护方法
保护Ability:通过在config.json里对应的Ability中配置"permissions": ["权限名"]属性,即可实现保护整个Ability的目的,无指定权限的应用不能访问此Ability。
保护API:若Ability对外提供的数据或能力有多种,且开放范围或保护级别也不同,可以针对不同的数据或能力在接口代码实现中通过verifyPermission(String permissionName, int pid, int uid)来对uid标识的调用者进行鉴权。
约束与限制
同一应用自定义权限个数不能超过1024个。
同一应用申请权限个数不能超过1024个。
为避免与系统权限名冲突,应用自定义权限名不能以ohos开头,且权限名长度不能超过256字符。
自定义权限授予方式不能为user_grant。
自定义权限开放范围不能为restricted。
权限开发
场景介绍
HarmonyOS支持开发者自定义权限来保护能力或接口,同时开发者也可申请权限来访问受权限保护的对象。
权限申请
开发者需要在config.json文件中的“reqPermissions”字段中声明所需要的权限。
{ "module": { "reqPermissions": [ { "name": "ohos.permission.CAMERA", "reason": "$string:permreason_camera", "usedScene": { "ability": ["com.mycamera.Ability", "com.mycamera.AbilityBackground"], "when": "always" } },{ ... } ] } }
权限申请格式采用数组格式,可支持同时申请多个权限,权限个数最多不能超过1024个。
如果声明使用的权限的grantMode是system_grant,则权限会在当应用安装的时候被自动授予。
如果声明使用的权限的grantMode是user_grant,则必须经用户手动授权(用户在弹框中授权或进入权限设置界面授权)才可使用。用户会看到reason字段中填写的理由,来帮助用户决定是否给予授权。
说明
对于授权方式为user_grant的权限,每一次执行需要这一权限的操作时,都需要检查自身是否有该权限。当自身具有权限时,才可继续执行,否则应用需要请求用户授予权限。
自定义权限
开发者需要在config.json文件中的“defPermissions”字段中自定义所需的权限:
{ "module": { "defPermissions": [ { "name": "com.myability.permission.MYPERMISSION", "grantMode": "system_grant", "availableScope": ["signature"] }, { ... } ] } }
权限定义格式采用数组格式,可支持同时定义多个权限,自定义的权限个数最多不能超过1024个。
defPermissions权限定义字段说明
权限授予方式字段说明
权限限制范围字段说明
访问权限控制
Ability的访问权限控制
在config.json中填写“abilities”的“permissions”字段,即只有拥有该权限的应用可访问此Ability。下面的例子表明只有拥有“ohos.permission.CAMERA”权限的应用可以访问此ability。
"abilities": [ { "name": ".MainAbility", "description": "$string:description_main_ability", "icon": "$media:hiworld", "label": "HiCamera", "launchType": "standard", "orientation": "portrait", "visible": false, "permissions": [ "ohos.permission.CAMERA" ], } ]
权限保护字段说明
Ability接口的访问权限控制
在Ability实现中,如需要对特定接口对调用者做访问控制,可在服务侧的接口实现中,主动通过verifyCallingPermission、verifyCallingOrSelfPermission来检查访问者是否拥有所需要的权限。
if (verifyCallingPermission("ohos.permission.CAMERA") != IBundleManager.PERMISSION_GRANTED) { // 调用者无权限,做错误处理 } // 调用者权限校验通过,开始提供服务 API接口说明 应用权限接口说明
API接口说明
应用权限接口说明
动态申请权限开发步骤
在config.json文件中声明所需要的权限。
{ "module": { "reqPermissions": [ { "name": "ohos.permission.CAMERA", "reason": "$string:permreason_camera", "usedScene": { "ability": ["com.mycamera.Ability", "com.mycamera.AbilityBackground"], "when": "always"} }, { ... } ] } }
使用ohos.app.Context.verifySelfPermission接口查询应用是否已被授予该权限。
如果已被授予权限,可以结束权限申请流程。
如果未被授予权限,继续执行下一步。
使用canRequestPermission查询是否可动态申请。
如果不可动态申请,说明已被用户或系统永久禁止授权,可以结束权限申请流程。
如果可动态申请,使用requestPermissionFromUser动态申请权限。
if (verifySelfPermission("ohos.permission.CAMERA") != IBundleManager.PERMISSION_GRANTED) { // 应用未被授予权限 if (canRequestPermission("ohos.permission.CAMERA")) { // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示) requestPermissionsFromUser( new String[] { "ohos.permission.CAMERA" } , MY_PERMISSIONS_REQUEST_CAMERA); } else { // 显示应用需要权限的理由,提示用户进入设置授权 } } else { // 权限已被授予 }
通过重写ohos.aafwk.ability.Ability的回调函数onRequestPermissionsFromUserResult接收授予结果。
@Override public void onRequestPermissionsFromUserResult (int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_CAMERA: { // 匹配requestPermissions的requestCode if (grantResults.length > 0 && grantResults[0] == IBundleManager.PERMISSION_GRANTED) { // 权限被授予 // 注意:因时间差导致接口权限检查时有无权限,所以对那些因无权限而抛异常的接口进行异常捕获处理 } else { // 权限被拒绝 } return; } } }
应用权限列表
权限分类
HarmonyOS根据接口所涉数据的敏感程度或所涉能力的安全威胁影响,定义了不同开放范围与授权方式的权限来保护数据。
当前权限的开放范围分为:
all:所有应用可用
signature:平台签名应用可用
privileged:预置特权应用可用
restricted:证书可控应用可用
应用在使用对应服务的能力或数据时,需要申请对应权限。
已在config.json文件中声明的非敏感权限,会在应用安装时自动授予,该类权限的授权方式为系统授权(system_grant)。
敏感权限需要应用动态申请,通过运行时发送弹窗的方式请求用户授权,该类权限的授权方式为用户授权(user_grant)。
当应用调用服务时,服务会对应用进行权限检查,如果没有对应权限则无法使用该服务。
敏感权限
敏感权限的申请需要按照动态申请流程向用户申请授权。
非敏感权限
非敏感权限不涉及用户的敏感数据或危险操作,仅需在config.json中声明,应用安装后即被授权。
受限开放的权限
受限开放的权限通常是不允许三方应用申请的。如果有特殊场景需要使用,请提供相关申请材料到应用市场申请相应权限证书。如果应用未申请相应的权限证书,却试图在config.json文件中声明此类权限,将会导致应用安装失败。另外,由于此类权限涉及到用户敏感数据或危险操作,当应用申请到权限证书后,还需按照动态申请权限的流程向用户申请授权。