欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

Android中的权限管理(基于Permission ProtectionLevel)

来源: 开发者 投稿于  被查看 33792 次 评论:197

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用户可以操作,避免了安全问题。

 

用户评论