openharmony安全子系统之权限管理
概念 在OpenHarmony的日志系统中,如果频繁出现诸如“permission defined”等报错信息,这往往指向了一个核心问题——权限配置不当。OpenHarmony的权限体系相当复杂且全面,涵盖了多个层面,包括应用调用时所需的权限、系统文件对不同用户的访问权限、SELinux策略所强制执行的权限控制,以及沙箱环境中路径的访问权限等。下面分析每一种权限的配置方式。 权限配置一:应
概念
在OpenHarmony的日志系统中,如果频繁出现诸如“permission defined”等报错信息,这往往指向了一个核心问题——权限配置不当。OpenHarmony的权限体系相当复杂且全面,涵盖了多个层面,包括应用调用时所需的权限、系统文件对不同用户的访问权限、SELinux策略所强制执行的权限控制,以及沙箱环境中路径的访问权限等。下面分析每一种权限的配置方式。
权限配置一:应用调用时所需的权限
比如应用申请访问通讯录、位置信息、语音等权限时,需要配置如下
Stage模型:需要在应用的module.json5中声明权限,示例:
{
"module": {
"requestPermissions": [{
"name": "ohos.permission.INSTALL_BUNDLE",
"reason": "install bundle",
"usedScene": {
"ability": [
"KitFramework"
],
"when": "always"
}
},
{
"name": "ohos.permission.LISTEN_BUNDLE_CHANGE",
"reason": "install bundle",
"usedScene": {
"ability": [
"KitFramework"
],
"when": "always"
}
},
{
"name": "ohos.permission.GET_BUNDLE_INFO",
"reason": "install bundle",
"usedScene": {
"ability": [
"KitFramework"
],
"when": "always"
}
}]
}
}
当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败;
constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE";
bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback)
{
if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) {
HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters");
return false;
}
// 检查ohos.permission.INSTALL_BUNDLE权限是否被授予
if (CheckPermission(0, static_cast<const char *>(PERMISSION_INSTALL_BUNDLE)) != GRANTED) {
HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied");
return false; // 返回安装失败
}
// 安装流程
...
}
也可以用户手动授权,用户申请授权示例:
动态向用户申请权限是指在应用程序运行时向用户请求授权的过程。可以通过调用requestPermissionsFromUser()方法来实现。该方法接收一个权限列表参数,例如位置、日历、相机、麦克风等。用户可以选择授予权限或者拒绝授权。
import { abilityAccessCtrl, common, Permissions, UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
const permissions: Array<Permissions> = ['ohos.permission.LOCATION','ohos.permission.APPROXIMATELY_LOCATION'];
function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext): void {
let atManager: abilityAccessCtrl.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: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
})
}
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// ...
windowStage.loadContent('pages/Index', (err, data) => {
reqPermissionsFromUser(permissions, this.context);
// ...
});
}
// ...
}
上述方式授权后,调用如下接口去核实相关APP或进程是否有权限调用相关的API接口
接口名 | 描述 |
---|---|
int CheckPermission(int uid, const char *permissionName) | 检查指定UID的应用进程是否具有访问系统服务API的权限 |
int CheckSelfPermission(const char *permissionName) | 检查调用者是否具有访问系统服务API的权限 |
int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum) | 查询应用申请的所有权限,并检查权限是否被授予 |
int GrantPermission(const char *identifier, const char *permName) | 将指定权限授予应用程序 |
int RevokePermission(const char *identifier, const char *permName) | 收回应用程序的指定权限 |
int GrantRuntimePermission(int uid, const char *permissionName) | 应用运行时动态授予指定权限 |
int RevokeRuntimePermission(int uid, const char *permissionName) | 应用运行时动态撤销指定权限 |
上述API对应的源码路径base/security/access_token/interfaces/kits/napi/accesstoken/src/napi_atmanager.cpp,有兴趣的盆友可以去看看源码。
权限配置二:系统文件对不同用户的访问权限
在源码路径base/startup/init/services/etc/init.cfg或者hdcshell路径/etc/init下的cfg中在jobs管理中使用chmod
权限配置三:SELinux策略
设置selinux各个子系统的访问策略在base/security/selinux_adapter/sepolicy/ohos_policy里面的te文件中进行配置,具体配置方式可以查看https://laval.csdn.net/64ee90df4165333c3076badb.html
权限配置四:沙盒文件访问权限
沙盒机制是每个进程独立空间,如果你要将沙盒中的进程写到物理路径目录下,需要在/system/etc/sandbox或者在源码路径base/startup/appspawn/中修改appdata-sandbox.json或者appdata-sandbox64.json,将物理路径和沙盒路径映射起来,这样你的沙盒里的进程就可以访问物理路径的文件夹了。sandbox-path是沙盒路径,src-path是物理路径
例如
总结
当开发过程中碰到权限问题时,可以从上述几种权限配置中去排查,一般可以解决大多数权限相关的错误。
更多推荐
所有评论(0)