HarmonyOS应用程序访问控制探究

关于作者

白晓明
宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人
华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL
华为开发者学堂/51CTO学堂/CSDN学堂认证讲师
开放原子开源基金会2023开源贡献之星

一、引言

随着信息技术的飞速发展,移动应用程序已经成为人们生活和工作中不可或缺的一部分。然而,随之而来的是对应用程序安全性的更高要求,尤其在用户隐私保护方面。工信部一直高度重视用户隐私保护,并依据《个人信息保护法》、《电信条例》、《规范互联网信息服务市场秩序若干规定》、《电信和互联网用户个人信息保护规定》等相关法律法规规章,对涉及用户隐私获取做出明确的通知,防止未经用户授权访问用户隐私信息以及用户隐私信息的滥用。

HarmonyOS的应用程序访问控制机制在这种背景下显得尤为重要,不仅可以保护用户的个人信息,还可以提高应用程序的安全性和可靠性,增强用户对应用程序的信任。HarmonyOS应用程序中,默认情况下,应用只能访问有限的系统资源,需要访问额外的系统数据(包括用户个人数据)和功能,应用必须以明确的方式对外提供接口来共享其数据或功能。通过访问控制机制,避免数据或功能被不当或恶意使用。

我将继续深入探究HarmonyOS应用程序访问控制的原理、方法和实践,为开发者和用户提供有益的参考。通过对HarmonyOS访问控制机制的探究,我们可以更好地理解其工作原理和优势,为开发更加安全可靠的应用程序提供指导。同时,我们也可以为用户提供更好的使用体验,让用户更加放心地使用HarmonyOS应用程序。

二、HarmonyOS应用程序访问控制的重要性

1)保护用户数据安全

在移动应用程序中,用户的数据往往包含敏感信息,如个人身份信息、财务信息等。如果应用程序没有有效的访问控制机制,这些数据可能会被恶意应用程序窃取或滥用。HarmonyOS的访问控制机制可以限制应用程序对用户数据的访问权限,从而保护用户数据的安全。HarmonyOS根据不同的授权方式,权限类型分为以下两种:

  • system_grant(系统授权):在该类型的权限许可下,应用被允许访问的数据不会涉及到用户或设备的敏感信息,应用被允许执行的操作对系统或者其他应用产生的影响可控。申请该权限的应用系统会在用户安装应用时,自动把相应权限授予应用。

  • user_grant(用户授权):在该类型的权限许可下,应用被允许访问的数据将会涉及到用户或设备的敏感权限,应用被允许执行的操作可能对系统或其他应用产生严重的影响。该类型权限不仅需要在安装包中申请权限,还需要在应用动态运行时,通过发送弹窗的方式请求用户授权。在用户手动允许授权后,应用才会真正获取相应的权限,从而成功访问操作目标对象。

2)防止应用程序滥用权限

一些应用程序可能会过度申请权限,从而获取用户的隐私信息或进行不必要的操作。HarmonyOS的访问控制机制可以对应用程序的权限进行严格管理,防止应用程序滥用权限。HarmonyOS提出了受限开放的权限,比如允许读写用户公共目录的音频文件ohos.permission.READ_AUDIO/WRITE_AUDIO,允许应用使用全局悬浮窗的能力ohos.permission.SYSTEM_FLOAT_WINDOW等权限,若特殊场景需要使用这些受限开放权限,则需要提供相关申请材料到应用市场申请相应权限证书通过后,才可以正常使用。

3)提高系统安全性

HarmonyOS的访问控制机制不仅可以保护用户数据的安全,还可以提高系统的安全性。通过限制应用程序的访问权限,可以防止恶意应用程序对系统进行攻击或破坏。

三、HarmonyOS应用程序访问控制的原理

1)应用权限

HarmonyOS采用了权限管理机制,对应用程序的访问权限进行严格控制。应用程序在安装时需要声明所需的权限,用户在安装应用程序时可以查看这些权限并决定是否授予。在运行时,系统会根据应用程序的权限声明和用户的授权情况,对应用程序的访问请求进行权限检查。

为了防止应用过度索取和滥用权限,HarmonyOS中基于APL(Ability Privilege Level,元能力权限等级)等级,配置了不同的权限开放范围。应用APL等级分为以下三个等级,等级依次提高。

APL级别 说明
normal 默认情况下,应用的APL等级都是normal等级。
system_basic 该等级的应用服务提供系统基础服务。
system_core 该等级的应用服务提供操作系统核心能力。应用APL等级不允许配置为system_core。

根据权限对于不同等级应用有不同的开放范围,权限APL等级对应分为以下三个等级,等级依次提高。

APL级别 说明 开放范围
normal 允许应用访问超出默认规则的普通系统资源,如配置Wi-Fi信息、调用相机拍摄等。 这些系统资源的开放(包括数据和功能)对用户隐私以及其他应用带来的风险低。 APL等级为normal及以上的应用。
system_basic 允许应用访问操作系统基础服务(系统提供或者预置的基础功能)相关的资源,如系统设置、身份认证等。 这些系统资源的开放对用户隐私以及其他应用带来的风险较高。 - APL等级为system_basic及以上的应用。 - 部分权限对normal级别的应用受限开放,需要额外申请。
system_core 涉及开放操作系统核心资源的访问操作。这部分系统资源是系统最核心的底层服务,如果遭受破坏,操作系统将无法正常运行。 - APL等级为system_core的应用。 - 仅对系统应用开放。

2)沙箱机制

HarmonyOS采用了沙箱机制,系统中运行的应用程序均部署在受限保护的沙箱中,通过沙箱的安全隔离机制,可以限制应用程序的不当行为(如应用间非法访问数据、篡改设备等)。沙箱环境中每个程序都拥有唯一的ID(TokenID),系统基于此ID识别与限制应用的访问行为,从而提高系统的安全性。同时,沙箱机制还可以防止应用程序之间的互相干扰,提高系统的稳定性。

3)系统控件

HarmonyOS提供了系统Picker、安全控件等临时授权的方式替代权限申请,在特定的场景中,应用无需向用户申请权限也可以临时访问受限资源,实现精准化权限管控,更好地保护用户隐私。

  • 系统Picker:由系统独立进程实现,在应用拉起Picker,并由用户操作Picker后,应用可以获取Picker返回的资源或结果。举例说明,当应用需要读取用户图片时,可通过使用照片Picker,在用户选择所需要的图片资源后,直接返回该图片资源,而不需要授予应用读取图片文件的权限。

  • 安全控件:由系统提供UI控件,应用在界面内集成对应控件,用户点击后,应用将获得临时授权,从而执行相关操作。举例说明,当应用需要分享当前位置时,可使用位置控件,用户点击后,将会在本次前台期间获得精准定位的授权,可以调用位置服务获取精准定位。当发生灭屏、应用切后台、应用退出等任一情况时,临时授权结束。

四、 HarmonyOS应用程序访问控制开发指南

1)选择申请权限的方式

  • 最小权限原则:即在应用开发初期,开发者应仔细分析应用的功能和业务逻辑,确定所需的权限,避免过度申请权限,以免引起用户的疑虑和不信任。

  • 动态申请权限:即在应用运行时,根据实际业务场景动态申请权限,提高用户体验,减少不必要的权限请求干扰。

在HarmonyOS中每个权限的权限等级、授权方式不同,申请权限的方式也不同,开发者在申请权限前,需要先根据应用权限列表应用申请权限的方式(参见下表)查看能否申请目标权限。

权限类型 授权方式 操作路径
所有应用可申请 system_grant 声明权限 > 访问接口
所有应用可申请 user_grant 声明权限 > 向用户申请授权 > 访问接口
受限开放权限 system_grant 申请使用受限权限 > 声明权限 > 访问接口
受限开放权限 user_grant 申请使用受限权限 > 声明权限 > 向用户申请授权 > 访问接口

以位置服务(Location Kit)为例,应用需要检查是否已经获取用户授权访问设备位置信息,若未获取授权,可以向用户申请需要的位置权限。

权限名称 权限级别 授权方式 说明
ohos.permission.LOCATION normal user_grant 允许应用获取设备位置信息。 需要与模糊位置权限一起申请。
ohos.permission.APPROXIMATELY_LOCATION normal User_grant 允许应用获取设备模糊位置信息。

2)声明权限

根据实际的业务需要确定需要的权限后,需要在module.json5配置文件的requestPermissions标签中声明位置服务(Location Kit)所需的权限。

{
  "module": {
    ...
    "requestPermissions": [
      {
        "name": "ohos.permission.LOCATION", // 权限名称,为系统已定义的权限
        "reason": "$string:location_reason",    // 申请权限的原因,当申请权限为user_grant权限时该字段为必填
        "usedScene": {  // 用于描述权限使用场景,当申请权限为user_grant权限时该字段为必填
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"   // 调用时机(inuse:使用时;always:始终)
        }
      },
      {
        "name": "ohos.permission.APPROXIMATELY_LOCATION",
        "reason": "$string:location_reason",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"
        }
      }
    ]
  }
}

3)向用户申请授权封装

大多数应用程序都会根据业务需要向用户申请授权,可利用抽象理念将向用户申请授权代码封装成可复用的模块或组件。通过定义清晰的接口和规范,可以提高代码的可维护性和可扩展性,同时降低不同应用场景的适配难度。

在工程entry模块src/main/ets目录下创建common文件夹,用于存放工程需要的基础公共代码,比如常量类AppConstants、权限控制工具类PermissionUtil等。

common > utils目录创建ArkTS文件PermissionUtil,并使用export导出该类。

/**
 * @description 权限控制工具类
 * @author 白晓明
 */
export class PermissionUtil {

}

用户每次执行需要目标权限的操作时,应用都必须调用checkAccessToken()方法检查自身是否已经具有该权限,该方法返回已授权PERMISSION_GRANTED或未授权PERMISSION_DENIED。在PermissionUtil中添加静态方法checkPermissionGrant用于检查当前应用程序是否已经被授予权限。

/**
 * 校验应用是否被授予 {permission} 权限
 * @param permission
 * @returns
 */
static checkPermissionGrant(permission: Permissions): abilityAccessCtrl.GrantStatus {
  const atManager = abilityAccessCtrl.createAtManager();
  // 初始化grantStatus为未授权
  let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
  let tokenId: number = 0;
  try {
    // 获取应用程序的accessTokenID
    const bundleInfo: bundleManager.BundleInfo =
      bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
    const appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
    tokenId = appInfo.accessTokenId;
    // 校验应用是否被授予权限
    grantStatus = atManager.checkAccessTokenSync(tokenId, permission);
    console.log(`检查${permission}权限状态为:${grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED ? "未授权" : "已授权"}`);
  } catch (error) {
    const err = error as BusinessError;
    console.error(`检查${permission}权限异常:${JSON.stringify(err)}`);
    grantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;
  }
  return grantStatus;
}

在校验应用是否被授予权限时,若未授权,需要调用requestPermissionsFromUser()方法动态向用户申请权限(指应用程序运行时向用户请求授权的过程)。在PermissionUtil中添加静态方法reqPermissionFromUser方法动态向用户申请授权。

/**
 * 动态申请权限
 * @param permissions
 * @returns 
 */
static async reqPermissionFromUser(permissions: Permissions[]): Promise<number[]> {
  console.log(`[AppLogger]动态申请权限开始`);
  const atManager = abilityAccessCtrl.createAtManager();
  let result: PermissionRequestResult = { permissions: [], authResults: [] };
  try {
    result = await atManager.requestPermissionsFromUser(context, permissions);
  } catch (error) {
    const err = error as BusinessError;
    console.error(`[AppLogger]动态申请权限异常:${JSON.stringify(err)}`);
  }
  return result.authResults;
}

4)在UI中向用户申请授权

import { abilityAccessCtrl, Permissions } from '@kit.AbilityKit'
import { PermissionUtil } from '../common/utils/PermissionUtil';

@Entry
@Component
struct Index {

  private locationPermissions: Permissions[] = [
    'ohos.permission.LOCATION',
    'ohos.permission.APPROXIMATELY_LOCATION'
  ];

  async aboutToAppear(): Promise<void> {
    // 校验是否被授予定位权限
    let flag: boolean = false;
    for (const permission of this.locationPermissions) {
      flag = false;
      const grantStatus: abilityAccessCtrl.GrantStatus = PermissionUtil.checkPermissionGrant(permission);
      if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
        flag = true;
      }
    }
    if (!flag) {  // 未授权,则弹出授权提示弹窗
      await PermissionUtil.reqPermissionFromUser(this.locationPermissions);
    }
  }

  build() {...}
}

5)效果预览

image-20240815165844821.png
image-20240815170145341.png

五、结论

HarmonyOS应用程序访问控制机制是保障用户数据安全和系统安全的重要手段。通过权限管理、沙箱机制、系统控件等多种方法,HarmonyOS可以有效地限制应用程序对系统资源的访问权限,防止应用程序滥用权限和恶意攻击。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容