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

来源:互联网 发布:烟台软件开发招聘 编辑:程序博客网 时间:2024/06/06 09:37

     1、什么是protectionlevel呢?

      我们经常在AndroidManifest中使用权限,如果我们想让应用程序可以发短信,那么应该这样写:

 <uses-permission android:name="android.permission.SEND_SMS" />

      那么这个权限的定义是在哪里定义的呢?如下:

      frameworks/base/core/res/AndroidManifest.xml

<permission android:name="android.permission.SEND_SMS"        android:permissionGroup="android.permission-group.COST_MONEY"        android:protectionLevel="dangerous"        android:label="@string/permlab_sendSms"        android:description="@string/permdesc_sendSms" />
     这个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 callpublic 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卡的权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      我们需要把Android空间的Permission Mapping到OS的GID。

      我们看一个重要的类,frameworks\base\data\etc\Platform.xml

    <permission name="android.permission.WRITE_EXTERNAL_STORAGE" >        <group gid="sdcard_rw" />    </permission>

   

     对于申请了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里面申请权限外,我们还可以在frameworks\base\data\etc\Platform.xml,assign权限,如下:

<assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" />    <assign-permission name="android.permission.SEND_SMS" uid="shell" />    <assign-permission name="android.permission.CALL_PHONE" uid="shell" />    <assign-permission name="android.permission.READ_CONTACTS" uid="shell" />    <assign-permission name="android.permission.WRITE_CONTACTS" uid="shell" />    <assign-permission name="android.permission.READ_CALENDAR" uid="shell" />    <assign-permission name="android.permission.WRITE_CALENDAR" uid="shell" />    <assign-permission name="android.permission.READ_USER_DICTIONARY" uid="shell" />    <assign-permission name="android.permission.WRITE_USER_DICTIONARY" uid="shell" />    <assign-permission name="android.permission.ACCESS_FINE_LOCATION" uid="shell" />    <assign-permission name="android.permission.ACCESS_COARSE_LOCATION" uid="shell" />    <assign-permission name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" uid="shell" />    <assign-permission name="android.permission.ACCESS_NETWORK_STATE" uid="shell" />    <assign-permission name="android.permission.ACCESS_WIFI_STATE" uid="shell" />    <assign-permission name="android.permission.BLUETOOTH" uid="shell" />    <!-- System tool permissions granted to the shell. -->    <assign-permission name="android.permission.GET_TASKS" uid="shell" />    <assign-permission name="android.permission.CHANGE_CONFIGURATION" uid="shell" />    <assign-permission name="android.permission.REORDER_TASKS" uid="shell" />    <assign-permission name="android.permission.SET_ANIMATION_SCALE" uid="shell" />    <assign-permission name="android.permission.SET_PREFERRED_APPLICATIONS" uid="shell" />    <assign-permission name="android.permission.WRITE_SETTINGS" uid="shell" />    <assign-permission name="android.permission.WRITE_SECURE_SETTINGS" uid="shell" />    <assign-permission name="android.permission.BROADCAST_STICKY" uid="shell" />    <!-- Development tool permissions granted to the shell. -->    <assign-permission name="android.permission.SET_DEBUG_APP" uid="shell" />    <assign-permission name="android.permission.SET_PROCESS_LIMIT" uid="shell" />    <assign-permission name="android.permission.SET_ALWAYS_FINISH" uid="shell" />    <assign-permission name="android.permission.DUMP" uid="shell" />    <assign-permission name="android.permission.SIGNAL_PERSISTENT_PROCESSES" uid="shell" />    <!-- Internal permissions granted to the shell. -->    <assign-permission name="android.permission.FORCE_BACK" uid="shell" />    <assign-permission name="android.permission.BATTERY_STATS" uid="shell" />    <assign-permission name="android.permission.INTERNAL_SYSTEM_WINDOW" uid="shell" />    <assign-permission name="android.permission.INJECT_EVENTS" uid="shell" />    <assign-permission name="android.permission.SET_ACTIVITY_WATCHER" uid="shell" />    <assign-permission name="android.permission.READ_INPUT_STATE" uid="shell" />    <assign-permission name="android.permission.SET_ORIENTATION" uid="shell" />    <assign-permission name="android.permission.INSTALL_PACKAGES" uid="shell" />    <assign-permission name="android.permission.CLEAR_APP_USER_DATA" uid="shell" />    <assign-permission name="android.permission.DELETE_CACHE_FILES" uid="shell" />    <assign-permission name="android.permission.DELETE_PACKAGES" uid="shell" />    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="shell" />    <assign-permission name="android.permission.READ_FRAME_BUFFER" uid="shell" />    <assign-permission name="android.permission.DEVICE_POWER" uid="shell" />    <assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" />    <assign-permission name="android.permission.BACKUP" uid="shell" />    <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />    <assign-permission name="android.permission.ACCESS_DRM" uid="media" />    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
      shell进程的权限我们在Android中的权限管理(基于uid gid gids setUid),已经看到过其申请的权限对应的gids。那时候没有讲shell进程是怎么样申请的这个权限,这里解决了我们的疑问。

      由于platform.xml只有root用户可以操作,避免了安全问题。

1 0
原创粉丝点击