Android中的权限管理(基于Permission ProtectionLevel)
Android中的权限管理(基于Permission ProtectionLevel)
1、什么是protectionlevel呢?
我们经常在AndroidManifest中使用权限,如果我们想让应用程序可以发短信,那么应该这样写:
那么这个权限的定义是在哪里定义的呢?如下:
frameworks/base/core/res/AndroidManifest.xml
这个xml可以认为是系统apk使用的AndroidManifest.xml,该apk使用系统的私钥进行签名。
name:权限的名字,uses-permisson使用的。
permissionGroup:权限的分类,在提示用户安装时会把某些功能差不多的权限放到一类。
protectionLevel:分为Normal、Dangerous、Signature、SignatureOrSystem,我们后面会着重讲这个。
label:提示给用户的权限名。
description:提示给用户的权限描述。
2、protectionLevel
(1)Normal
权限被声明为Normal级别,任何应用都可以申请,在安装应用时,不会直接提示给用户,点击全部才会展示。
(2)Dangerous
权限被声明为Dangerous级别,任何应用都可以申请,在安装应用时,会直接提示给用户。
(3)Signature
权限被声明为Signature级别,只有和该apk(定义了这个权限的apk)用相同的私钥签名的应用才可以申请该权限。
frameworks/base/core/res/AndroidManifest.xml声明的权限为Signature级别,那么只有Android官方使用相同私钥签名的应用才可以申请该权限。
(4)SignatureOrSystem
权限被声明为SignatureOrSystem级别,有两种应用可以申请该权限。
1)和该apk(定义了这个权限的apk)用相同的私钥签名的应用
2)在/system/app目录下的应用
3、举个例子
比如百度地图apk的AndroidManifest.xml里面声明了一个权限,
(1)、权限定义为Dangerous,那么任何其他应用都可以使用。
(2)、权限定义为Signature,那么只有使用同样私钥签名的apk,例如百度网盘,可以使用这个权限。
(3)、权限定义为SignatureOrSystem,那么使用同样私钥签名的apk,例如百度网盘,可以使用这个权限。在/system/app下的应用也可以使用这个权限。
4、我们自然想到一个问题,申请了某个权限与否,在代码中是怎么控制是否可以访问某个资源呢?
(1)、Android系统独有的权限,在代码中是怎么控制是否可以访问某个资源呢?我们看一个实际的例子。
Client端:
void startDockOrHome(){ awakenDreams(); ...... } private static void awakenDreams(){ IDreamManager dreamManager = getDreamManager(); if(dreamManager != null){ try{ dreamManager.awaken();//调用Server端的awaken } catch(RemoteException e){ //fine, stay asleep then } }Server端:
@Override // Binder call public void awaken() { checkPermission(android.Manifest.permission.WRITE_DREAM_STATE); final long ident = Binder.clearCallingIdentity(); try { requestAwakenInternal(); } finally { Binder.restoreCallingIdentity(ident); } } private void checkPermission(String permission) { if (mContext.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException(Access denied to process: + Binder.getCallingPid() + , must have permission + permission); } }Client端和Server端通过Binder进程间通信机制来通信。在Server端通过checkPermission来检查Client端是否申明了此权限。
(2)、对于非Android特有的Service(底层平台已经提供,如File访问,TCPIP数据收发等),多个入口访问:Android API,Java API,NDK C API,shell都可以访问。这样权限控制就聚口在底层,所以在底层统一控制。这个底层统一控制其实就是传统的Linux文件读写执行权限(rwx)。
例如在应用中申请了写SD卡的权限:
我们需要把Android空间的Permission Mapping到OS的GID。
我们看一个重要的类,frameworksasedataetcPlatform.xml
对于申请了WRITE_EXTERNAL_STORAGE特权的应用,该应用的进程的gids就包含了sdcard_r,就可以对sd卡中的文件进行操作了。
再看Android_filesystem_config.h的源码:
#define AID_SDCARD_RW 1015 /* external storage write access */
也就是说这个权限映射到1015的gid,我们再来看一张图:
我们查看com.android.phone这个进程,该应用申请了写外部内存卡的权限。首先使用ps查看该进程的进程号是1038,然后采用如下命令:
我们看到这个进程的Groups里面有gid为1015,1015就是对应sdcard_r。
5、除了我们在AndroidManifest.xml里面申请权限外,我们还可以在frameworksasedataetcPlatform.xml,assign权限,如下:
shell进程的权限我们在Android中的权限管理(基于uid gid gids setUid),已经看到过其申请的权限对应的gids。那时候没有讲shell进程是怎么样申请的这个权限,这里解决了我们的疑问。
由于platform.xml只有root用户可以操作,避免了安全问题。
用户评论