系统权限
本文档
安全架构
应用程序签名
用户ID和文件访问
使用权限
声明并强制执行的权限
...在AndroidManifest.xml
...发送广播时
其他执法权限
URI权限
Android是一个特权分隔的操作系统,其中每个应用程序与不同的系统标识(Linux的用户ID和组ID)上运行。该系统的部件也被分离成不同的身份。的Linux从而隔离彼此并从系统中的应用程序。
通过实施具体操作的特定进程可以执行限制“权限”机制提供了额外的细粒度的安全功能,和每URI的授予特定的数据段临时访问权限。
本文介绍了如何应用程序开发人员可以使用由Android提供的安全功能。一个更普遍的Android安全性概述在Android开源项目提供。
安全架构
Android的安全架构的核心设计的一点是,没有应用程序,默认情况下,必须执行,将其他应用程序,操作系统,或者用户造成不利影响的任何操作的权限。这包括读取或写入用户的私人数据(如联系人或电子邮件),读取或写入其他应用程序的文件,访问网络,保持清醒的设备,等等。
由于每个Android应用程序在一个进程中运行的沙箱,应用程序必须明确共享资源和数据。他们通过声明自己需要不是由基本沙箱提供的额外功能的权限做到这一点。应用静态宣布他们所需的权限,和Android系统提示您同意用户在安装应用程序的时间。 Android有没有机制(在运行时)动态地授予权限,因为它的复杂性的用户体验到的安全性受到损害。
应用程序沙箱不依赖于用于构建应用程序的技术。尤其是Dalvik虚拟机并不是一个安全边界,任何应用程序可以运行本地代码(见的Android NDK)。所有类型的应用 - 爪哇,天然和混合 - 均沙盒以同样的方式和具有彼此相同程度的安全性。
应用程序签名
所有的APK(.apk文件的文件)必须使用的私钥由开发商自己持有的证书进行签名。此证书标识应用程序的作者。该证书并不需要由证书颁发机构签署;这是完全允许的,和典型,Android应用程序使用自签名的证书。 Android中证书的目的是区分应用程序的作者。这使得系统授予或拒绝应用程序访问签名级别权限,并授予或拒绝应用程序的请求,给予相同的Linux身份另一个应用程序。
用户ID和文件访问
在安装时,Android为每个包一个独特的Linux用户ID。身份仍然是包的生命的设备上的时间常数。在不同的装置中,相同的包可具有不同的UID;重要的是,每个包都有一个特定设备上的不同的UID。
因为安全强制发生在工艺水平,任何两个包的代码不能正常在同一进程中运行,因为它们需要运行不同Linux用户。您可以使用sharedUserId属性在AndroidManifest.xml的每个包的清单标签让他们分配了相同的用户ID。通过这样做,对于安全目的的两个包然后被作为是相同的应用程序,使用相同的用户ID和文件权限处理。需要注意的是,为了保持安全性,具有相同签名(和请求相同sharedUserId)签署只有两个应用程序将被给予相同的用户ID。
由一个应用程序存储在任何数据都将被分配一个应用程序的用户的ID,并且通常不会对其他的包访问。当创建与getSharedPreferences(字符串,整数),openFileOutput(字符串,整数),或openOrCreateDatabase(字符串,整数,SQLiteDatabase.CursorFactory),您可以使用MODE_WORLD_READABLE和/或MODE_WORLD_WRITEABLE标志允许任何其他程序包来读取一个新的文件/写入文件。当设置这些标志,该文件仍然是由您的应用程序拥有,但其全球读取和/或写入权限设置相应使其他任何应用程序都可以看到它。
使用权限
一个基本的Android应用程序没有默认与之关联的,这意味着它不能做任何事情,将用户体验或设备上的任何数据产生不利影响的权限。要使用的设备的保护功能,您必须在您的AndroidManifest.xml中的一个或多个<使用许可权>标签声明权限您的应用需求。
例如,需要监控收到的短信应用程序会指定:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.app.myapp" >
<uses-permission android:name="android.permission.RECEIVE_SMS" />
...
</manifest>
在应用程序安装时,应用程序所请求的权限由安装程序包赋予它的基础上,宣布对这些权限和/或与用户交互的应用程序的签名支票。与用户的检查,同时应用程序运行完成的;应用程序是将授予特定权限安装的时候,并根据需要可以使用该功能,或者不被许可的任何企图使用该功能不提示用户将失败。
很多时候,一个权限失败将导致抛出SecurityException返回给应用程序。但是,这不能保证到处发生。例如,sendBroadcast(意向)方法检查的权限,数据被传递到每个接收器,该方法调用返回之后,因此,如果有权限的失败,你将不会收到异常。在几乎所有的情况下,然而,一个许可失败将被打印到系统日志。
但是,在普通用户的情况(当应用程序从谷歌Play商店安装,如),应用程序不能,如果用户不授予应用程序的每个请求的权限安装。因此,你一般不需要担心造成失踪的权限运行时失败,因为这一事实,该应用程序安装在所有这些都意味着你的应用程序已获得其所需的权限。
通过Android系统提供的权限可以在Manifest.permission找到。任何应用程序还可以定义并执行它自己的权限,所以这不是所有可能的权限的完整列表。
特定权限可以在一些程序的运行过程中的地方被执行:
在呼叫进入该系统的时间,以防止在执行某些功能的应用程序。
当启动一个活动,以防止应用程序启动其他应用程序的活动。
发送和接收广播,以控制谁可以收到您的广播或谁可以广播发送给您。
当访问和内容提供商操作。
结合或启动服务。
注意:随着时间的推移,新的限制可以被添加到该平台,使得在为了使用某些API,应用程式必须请求它以前并不需要许可。由于现有的应用程序承担访问这些API是免费提供的,Android的,可申请新的许可请求的应用程序的清单,以避免破坏在新的平台版本的应用程序。 Android的做出决定作为一个应用程序是否可能需要根据所提供的targetSdkVersion属性值的权限。如果该值大于在其中加入许可的版本下,则Android添加权限。
例如,WRITE_EXTERNAL_STORAGE准许在API级别4加入到限制访问共享存储空间。如果您targetSdkVersion为3或更低,此权限将被添加到您的应用程序在Android的新版本。
请注意,如果发生这种情况,您的应用程序,在谷歌的应用详情播放将显示这些所需的权限,即使您的应用程序可能实际上不需要它们。
为了避免这种情况并删除不需要的默认权限,随时更新你的targetSdkVersion要尽可能的高。您可以看到与Build.VERSION_CODES文档中的每个版本中添加的权限。
声明并强制执行的权限
要实施您自己的权限,则必须使用一个或多个<许可>标签首先申报日时间在的AndroidManifest.xml。
例如,想要控制谁的应用程序可以启动它的活动之一,如下所示可以宣布此操作的权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.me.app.myapp" >
<permission android:name="com.me.app.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>
在<的ProtectionLevel>属性是必需的,告诉系统用户是如何被告知需要,或者谁被允许持有该权限,作为链接文档中描述的许可申请。
在<permissionGroup>属性是可选的,并且只用于帮助系统显示的权限给用户。通常你会想将它设置为一个标准的系统组或更罕见的情况下给一个自己定义的(在android.Manifest.permission_group列出)。优选使用现有的组,因为这简化了显示给用户的权限的用户界面。
注意,一个标签和描述应为许可提供。这些是可以当他们正在查看的权限(机器人:标签)的列表中显示给用户的字符串资源在单一许可或细节(安卓描述)。标签要短,描述功能的关键一块权限保护的几句话。描述应说明何种权限,允许持有人做一两句。我们对会议的描述是两句话,第一个描述许可,第二个警告,如果一个应用程序被授予的权限,会发生什么不好的事情了用户。
这里是一个标签和描述为CALL_PHONE许可的例子:
<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the application to call
phone numbers without your intervention. Malicious applications may
cause unexpected calls on your phone bill. Note that this does not
allow the application to call emergency numbers.</string>
你可以看一下目前的设置应用程序和shell命令亚行外壳时许列表的权限系统定义的权限。要使用设置应用程序,进入设置>应用程序。选择一个应用程序,并滚动查看该应用程序使用的权限。对于开发商来说,亚洲开发银行“-S”选项显示类似于用户会怎么看他们的形式的权限:
$ adb shell pm list permissions -s
All Permissions:
Network communication: view Wi-Fi state, create Bluetooth connections, full
Internet access, view network state
Your location: access extra location provider commands, fine (GPS) location,
mock location sources for testing, coarse (network-based) location
Services that cost you money: send SMS messages, directly call phone numbers
...
高级别权限限制访问系统或应用程序的整个组件可以通过你的AndroidManifest.xml中的应用。所有这需要由包括一个机器人:所希望组分上允许属性,命名将用于控制访问它的权限。
活动权限(应用于<活动>标签)限制谁可以启动相关的活动。 Context.startActivity()和Activity.startActivityForResult()过程中的权限检查;如果调用者不具备所需的权限,然后SecurityException异常从调用抛出。
服务权限(应用于<服务>标签)限制谁可以启动或绑定到相关的服务。 Context.startService(),Context.stopService()和Context.bindService()过程中的权限检查;如果调用者不具备所需的权限,然后SecurityException异常从调用抛出。
BroadcastReceiver的权限(应用于<接收>标签)限制谁可以发送广播到相关的接收器。作为系统试图提交的广播传送到指定的接收方的许可后Context.sendBroadcast检查()返回。其结果是,许可故障不会导致抛出异常返回给调用者;它只是无法实现的意图。以同样的方式,权限可以提供给Context.registerReceiver(),以控制谁可以广播到编程注册接收机。要的其他方式,权限可以供给调用Context.sendBroadcast时(),以限制该广播接收器对象被允许接收广播(见下文)。
ContentProvider的权限(应用于<提供商>标签)限制谁可以在ContentProvider的访问数据。 (内容提供者提供给他们的重要额外的安全设施称为后述的URI的权限。)与其它组分,有两个单独的许可属性可设置:雄编号:readPermission限制谁可以从提供读出,机器人:writePermission限制谁可以写它。需要注意的是,如果一个提供商既具有读写权限保护,只有持有写权限并不意味着你可以从供应商读取。权限检查时,首先检索提供商(如果你没有任何权限,一则抛出SecurityException),并且您在供应商的操作。使用ContentResolver.query()需要持有读取权限;使用ContentResolver.insert(),ContentResolver.update(),ContentResolver.delete()需要写入权限。在所有这些情况下,不是拿着一个SecurityException所需的权限结果从通话中被抛出。
发送广播时,执行权限
除了权限执行谁可以将意向发送给注册的广播接收器(如上所述),您也可以发送广播时指定所需的权限。通过与一个权限字符串调用Context.sendBroadcast(),则需要一个接收器的应用程序必须认为权限,才能收到您的广播。
注意,这两个接收器和一个广播装置可能需要的权限。当发生这种情况,既权限检查必须通过为意图被传递给相关的目标。
其他执法权限
任意细粒度的权限,可以在任何呼叫转变为服务执行。这是与Context.checkCallingPermission()方法来实现的。与所需的许可权字符串调用,它会返回一个整数,表示该权限是否已经被授予当前调用进程。请注意,当正在执行一个呼叫从另一种方法来在,通常是通过从服务或在给予另一过程中的一些其它方式发表IDL接口这只能使用。
还有一些其他有用的方法来检查许可。如果您有其他进程的PID,您可以使用上下文方法Context.checkPermission(字符串,INT,INT)来检查针对PID的权限。如果你有其他应用程序的软件包名称,你可以使用直接软件包管理系统方法PackageManager.checkPermission(字符串,字符串)找出特定的包是否已授予特定权限。
URI权限
与内容提供商当用于到目前为止所描述的标准的许可系统往往是不足够的。内容提供者可能想保护自己的读写权限,而其直接的用户还需要手工特定的URI到其它应用程序对他们进行操作。一个典型的例子是在邮件应用程序的附件。到邮件访问应该由权限得到保护,因为这是敏感的用户数据。但是,如果一个URI到图像附件是考虑到一个图像浏览器,该图片浏览器将没有权限打开附件,因为它没有理由持有访问所有电子邮件的权限。
这个问题的解决方案是每-URI权限:开始一个活动或一个结果返回到活动时,主叫方可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION和/或Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这将授予的接收活动许可访问的特定数据中的URI意图,不管它是否具有在对应于意图的内容提供者以访问数据的许可。
此机制允许共同能力式模型,其中用户交互(打开附件,从列表中选择一个联系人,等等)驱动细粒度权限临时授予。这可以是用于降低由应用到只有那些直接关系到其行为所需的权限的密钥设施。
细粒度权限URI授予确实,但是,需要与内容提供商拿着这些URI有一些合作。强烈建议内容提供商实现这个设施,并宣布他们支持通过Android:grantUriPermissions属性或<赠款URI的权限>标记。
更多的信息可以在Context.grantUriPermission(),Context.revokeUriPermission(),和Context.checkUriPermission()方法被发现。