该文档描述了应用程序开发人员如何使用Android提供的安全特性来定义自己的权限。通过定义自定义权限,应用程序可以与其他应用程序共享资源和功能
背景
Android是一个特权分离的操作系统,在这个系统中,每个应用程序都运行一个不同的系统标识(Linux用户标识和组标识)。系统的部分也被分离成不同的身份。因此,Linux将应用程序与系统隔离开来。
应用程序可以通过定义其他应用程序可以请求的权限向其他应用程序公开它们的功能。它们还可以定义与相同证书签署的任何其他应用程序自动可用的权限。
应用程序签名(就是是否接受使用同签名)
所有apk都必须使用由其开发人员持有的私钥的证书进行签名。此证书标识应用程序的作者。证书不需要由证书颁发机构签署;这是完全允许的,而且是典型的,Android应用程序使用自签名证书。Android中证书的目的是区分应用程序作者。这允许系统授予或拒绝应用程序对签名级别权限的访问,以及授予或拒绝应用程序与其他应用程序相同的Linux标识。
用户ID和文件访问
在安装时,Android会给每个包一个不同的Linux用户ID,在这个设备上,这个ID在包的整个生命周期中都是不变的。在不同的设备上,相同的包可能有不同的UID;重要的是每个包在给定的设备上都有一个不同的UID。
由于安全性强制发生在进程级别(process level),因此任何两个包的代码通常不能在同一个进程中运行,因为它们需要作为不同的Linux用户运行。您可以在AndroidManifest中使用sharedUserId属性。xml的每个包的manifest标记为它们分配相同的用户ID,通过这样做,为了安全起见,这两个包将被视为具有相同用户ID和文件权限的相同应用程序。注意,为了保持安全性,只有两个签名相同的应用程序(以及请求相同的sharedUserId)将获得相同的用户ID。
要执行自己的权限,必须首先在AndroidManifest中声明它们。使用一个或多个<permission>元素的xml。
例如,一个想要控制谁可以开始其活动的应用程序可以声明此操作的权限如下:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp" >
<permission
android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
android:label="@string/permlab_deadlyActivity"
android:description="@string/permdesc_deadlyActivity"
android:permissionGroup="android.permission-group.COST_MONEY"
android:protectionLevel="dangerous" />
...
</manifest>
注意:系统不允许多个包声明具有相同名称的自定义权限,除非所有包都用相同的证书签名。如果包声明一个权限,系统不允许用户安装具有相同权限名的其他包,除非这些包与第一个包签署了相同的证书。为了避免命名冲突,我们建议使用反向域样式的命名来命名自定义权限,例如com.example.myapp.ENGAGE_HYPERSPACE。
android:protectionLevel 为权限的安全级别,这里按从低到高的顺序有以下四种:
- normal:默认值。一种风险较低的权限,不需要用户显示同意。
- dangerous:高风险权限,需要显示请求用户同意。
- signature:只有该权限的申请者和请求者有相同的签名时才被允许。(签名限制)
- signatureOrSystem:旧版“signature|privileged”的同义词。在API级别23中被弃用。
系统只授予位于Android系统映像的专用文件夹中的应用程序或与声明权限的应用程序签署相同证书的应用程序的权限。避免使用此选项,因为签名保护级别应该足以满足大多数需求,并且不管应用程序安装在什么地方都可以工作。“signatureOrSystem”权限用于某些特殊情况,在这些特殊情况下,多个供应商将应用程序构建到系统映像中,并且需要显式地共享特定的特性,因为它们是构建在一起的。(就是比signature多了一个可允许的条件:系统应用)
permissionGroup属性是可选的,只用于帮助系统向用户显示权限。在大多数情况下,您应该将其设置为一个标准的系统组(在android.Manifest.permission_group中列出),尽管您可以自己定义一个组。最好使用一个现有的组,因为这样可以简化显示给用户的权限UI。
您需要为权限提供一个标签(label)和描述(description)。当用户查看权限列表(android:label)或单个权限细节(android:description)时,可以看到这些字符串资源。标签应简短;描述权限所保护的关键功能的几个词。描述应该是几个句子描述权限允许持有者做什么。我们的约定是两句话的描述:第一句描述权限,第二句警告用户,如果应用程序被授予权限,可能会出错。
下面是CALL_PHONE权限的标签和描述示例:(这个好像不简短啊..)
<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call
phone numbers without your intervention. Malicious apps may
cause unexpected calls on your phone bill. Note that this does not
allow the app to call emergency numbers.</string>
创建一个权限组
如前一节所示,可以使用android:permissionGroup属性帮助系统向用户描述权限。在大多数情况下,您希望将其设置为一个标准的系统组(在android.Manifest.permission_group中列出),但是您也可以使用<permission-group>定义您自己的组。
<permission-group>元素为一组permission定义了一个标签——包括在manifest中声明为<permission>的元素和在别处声明的元素。这只影响在呈现给用户时如何将权限分组。<permission-group>元素没有指定属于组的权限,但它给组一个名称。
通过将组名分配给<permission>元素的permissionGroup属性,可以在组中放置权限。
<permission-tree>元素为代码中定义的一组权限声明一个名称空间。