System Permissions

System Permissions
系统权限

Android is a privilege-separated operating system, in which each application runs with a distinct system identity (Linux user ID and group ID). Parts of the system are also separated into distinct identities. Linux thereby isolates applications from each other and from the system.
安卓是一个权限分离的操作系统,每一个应用以不同的系统身份运行(Linux用户ID和组ID)。系统部件也分为不同的身份。因此Linux将应用程序在系统中互相分离。

Additional finer-grained security features are provided through a “permission” mechanism that enforces restrictions on the specific operations that a particular process can perform, and per-URI permissions for granting ad hoc access to specific pieces of data.
另外细分化的安全特征提供了通过“权限”机制来强制限制某个进程可以执行某些特定的操作。per-URI权限用来提供ad hoc(点对点)式的对特定的数据块的访问。

This document describes how application developers can use the security features provided by Android. A more general Android Security Overview is provided in the Android Open Source Project.
这篇文档描述了怎样让开发者使用安卓提供的安卓特性。安卓开源代码项目提供了更多安卓安全概述。

Security Architecture
安全架构


A central design point of the Android security architecture is that no application, by default, has permission to perform any operations that would adversely impact other applications, the operating system, or the user. This includes reading or writing the user’s private data (such as contacts or emails), reading or writing another application’s files, performing network access, keeping the device awake, and so on.
安卓安全架构设计的一个重点是:没有应用能够在默认情况下有权限执行任何能够给其他应用,操作系统或者用户带来不利的影响的操作。这包括了读写用户隐私数据(比如联系人和邮件),读写其他应用的文件,执行网络访问,保持设备唤醒状态等等。

Because each Android application operates in a process sandbox, applications must explicitly share resources and data. They do this by declaring the permissions they need for additional capabilities not provided by the basic sandbox. Applications statically declare the permissions they require, and the Android system prompts the user for consent at the time the application is installed. Android has no mechanism for granting permissions dynamically (at run-time) because it complicates the user experience to the detriment of security.
因为每一个安卓应用运行在独立的沙盒进程,所以应用程序必须显式地共享资源和数据。为此他们要声明额外的而基础沙箱不提供的功能权限。应用静态的声明他们需要的权限,应用安装时安卓系统会提醒用户同意。安卓没有动态授权机制(在运行时)因为这会复杂化用户体验并降低安全性。

The application sandbox does not depend on the technology used to build an application. In particular the Dalvik VM is not a security boundary, and any app can run native code (see the Android NDK). All types of applications — Java, native, and hybrid — are sandboxed in the same way and have the same degree of security from each other.
安卓应用沙盒并不依赖于构建应用程序的技术。尤其是在Dalvik 虚拟机并不是一个安全的防线的情况下,任何应用都可以运行原生代码(请查看android NDK)。所有类型的应用——Java,原生的,混合的,都使用相同的方法沙盒化,并且有相同的安全等级。

Application Signing
应用程序认证


ll APKs (.apk files) must be signed with a certificate whose private key is held by their developer. This certificate identifies the author of the application. The certificate does not need to be signed by a certificate authority; it is perfectly allowable, and typical, for Android applications to use self-signed certificates. The purpose of certificates in Android is to distinguish application authors. This allows the system to grant or deny applications access to signature-level permissions and to grant or deny an application’s request to be given the same Linux identity as another application.

所有的APK文件必须通过它的开发者所私有的证书进行认证。证书标识了应用程序的作者。证书不需要通过证书授证中心的认证。这是完全允许的,标准的安卓应用进行自认证证书。安卓系统使用证书的目的是区别应用开发者。这允许系统去运行或拒绝应用程序访问签名等级的权限或者请求给与其他应用相同Linux ID。

User IDs and File Access
用户ID和文件访问


At install time, Android gives each package a distinct Linux user ID. The identity remains constant for the duration of the package’s life on that device. On a different device, the same package may have a different UID; what matters is that each package has a distinct UID on a given device.
在安装时,安卓给每个包一个独特的Linux用户ID。在程序包存在于设备上时ID是不会变的。在不同的设备上,相同的安装包可能有不同的UID。重要的是设备上每个安装包都有一个独立的ID。

Because security enforcement happens at the process level, the code of any two packages cannot normally run in the same process, since they need to run as different Linux users. You can use the sharedUserId attribute in the AndroidManifest.xml’s manifest tag of each package to have them assigned the same user ID. By doing this, for purposes of security the two packages are then treated as being the same application, with the same user ID and file permissions. Note that in order to retain security, only two applications signed with the same signature (and requesting the same sharedUserId) will be given the same user ID.
因为安全的程序运行反生在进程级别,任何两个包的代码通常不能的运行在相同的进程中,因为它们需要运行在不同的Linux用户下。你可以在安卓Manifest文件中的Manifest标签使用共享用户ID属性为每个包分配相同的用户ID。这样,为了安全性,两个应用被视为相同的应用程序,有着相同的用户ID和文件权限。注意:为了保证安全。只有两个程序被签署了相同的签名(请求相同的sharedUserId)才会被给与相同的用户ID。

Any data stored by an application will be assigned that application’s user ID, and not normally accessible to other packages. When creating a new file with getSharedPreferences(String,int),openFileOutput(String,int),oropenOrCreateDatabase(String,int,SQLiteDatabase.CursorFactory), you can use the MODE_WORLD_READABLE and/or MODE_WORLD_WRITEABLE flags to allow any other package to read/write the file. When setting these flags, the file is still owned by your application, but its global read and/or write permissions have been set appropriately so any other application can see it.
应用储存任何数据的时候都需要指定应用的用户ID,正常情况下不能访问其他包(应用)的文件。当使用getSharedPreferences(String,int), openFileOutput(String,int), oropenOrCreateDatabase(String,int,SQLiteDatabase.CursorFactory)创建新的文件时,你可以使用MODE_WORLD_READABLE或者MODE_WORLD_WRITEABLE标识来允许其他应用读写该文件。当设置了这个标识。文件仍然属于你的应用,但是文件设置了全局读写权限,所以任何其他应用都可以访问它。

Using Permissions
使用权限


A basic Android application has no permissions associated with it by default, meaning it cannot do anything that would adversely impact the user experience or any data on the device. To make use of protected features of the device, you must include in your AndroidManifest.xml one or more <
uses-permission> tags declaring the permissions that your application needs.
一个基本的安卓应用默认情况下是没有权限的,这意味着它不能做任何损害用户体验和数据的事情。为了让用户保护设备特性,你必须在你的Manifest文件中加入一个或者多个<
uses-permission>标签来声明你的应用需要的权限。

For example, an application that needs to monitor incoming SMS messages would specify:
例如,一个应用程序需要监控收到的信息可以指定:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.app.myapp" >
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    ...
</manifest>

At application install time, permissions requested by the application are granted to it by the package installer, based on checks against the signatures of the applications declaring those permissions and/or interaction with the user. No checks with the user are done while an application is running; the app is either granted a particular permission when installed, and can use that feature as desired, or the permission is not granted and any attempt to use the feature fails without prompting the user.

在应用程序安装时,权限需求需要安装程序的同意,基于检查应用签名授予应用程序声明它的些权限和用户交互行为。在程序运行时不再检查。除非是安装时获取特定的许可,才可以使用期望的特性,否则在不提示用户的情况下,不允许任何企图使用特性的行为。

Often times a permission failure will result in a SecurityException being thrown back to the application. However, this is not guaranteed to occur everywhere. For example, the sendBroadcast(Intent) method checks permissions as data is being delivered to each receiver, after the method call has returned, so you will not receive an exception if there are permission failures. In almost all cases, however, a permission failure will be printed to the system log.
通常情况下权限被拒绝时会使程序抛出一个SecurityException异常。 然而,并不能保证每次都会抛出。例如,当sendBroadcast(Intent)方法检查权限时数据已经发送到了接收器,当方法返回时,你不会收到权限被拒绝的异常。但是,在绝大多数情况下,权限被拒绝异常都会在系统日志打印出来。

However, in a normal user situation (such as when the app is installed from Google Play Store), an app cannot be installed if the user does not grant the app each of the requested permissions. So you generally don’t need to worry about runtime failures caused by missing permissions because the mere fact that the app is installed at all means that your app has been granted its desired permissions.
然而,在通常情况下(比如app是通过Google Play安装的),一个app不能在用户没有通用所有的权限请求的情况下进行安装。所以在通常情况下你不需要担心在运行时会缺少权限,因为事实上应用安装完成毫无疑问的意味着你的应用已经被授予了想要的权限。

The permissions provided by the Android system can be found at Manifest.permission. Any application may also define and enforce its own permissions, so this is not a comprehensive list of all possible permissions.
安卓系统提供的权限可以在Manifest.permission中找到。任何应用也许可以定义和执行自己用于的权限,所以这并不是所有权限的列表。

A particular permission may be enforced at a number of places during your program’s operation:
一个特殊的权限可能在会在你的程序操作的多个地方执行:

  • At the time of a call into the system, to prevent an application from executing certain functions.
  • Both sending and receiving broadcasts, to control who can receive your broadcast or who can send a broadcast to you.
  • When accessing and operating on a content provider. Binding to or starting a service.
  • 在进行系统调用时,防止应用执行某些应用。
  • 同时发送和接受广播,管理谁可以接受你的广播和谁可以发送广播给你。
  • 当访问和操作一个内容控制器的时候,还有绑定或者启动service的时候。

Caution: Over time, new restrictions may be added to the platform such that, in order to use certain APIs, your app must request a permission that it previously did not need. Because existing apps assume access to those APIs is freely available, Android may apply the new permission request to the app’s manifest to avoid breaking the app on the new platform version.
随着时间变化,新的限制可能会被加入到平台中,就像为了使用某个API,你的app必须请求一个以前的不需要的权限。因为现有的应用可以随时访问这些API,所以为了避免新的平台版本对之前的应用造成损坏,安卓可能会申请新的权限请求到应用的Manifest中。
Android makes the decision as to whether an app might need the permission based on the value provided for the targetSdkVersion attribute. If the value is lower than the version in which the permission was added, then Android adds the permission.
安卓根据targetSdkVersion属性提供的值来决定一个app是否需要某个权限。如果值低于该权限加入的版本,安卓就会添加该权限
For example, the WRITE_EXTERNAL_STORAGE permission was added in API level 4 to restrict access to the shared storage space. If your targetSdkVersion is 3 or lower, this permission is added to your app on newer versions of Android.
例如 用来限制访问共享储存空间的WRITE_EXTERNAL_STORAGE 权限是在API等级4加入的。如果你的targetSdkVersion是3或者更低,在新版本的安卓系统这个权限就会被加入到你的应用中。
Beware that if this happens to your app, your app listing on Google Play will show these required permissions even though your app might not actually require them.
To avoid this and remove the default permissions you don’t need, always update your targetSdkVersion to be as high as possible. You can see which permissions were added with each release in the Build.VERSION_CODES documentation.
要注意在你的应用发生这种情况,你发布在Google Play 上的应用将会显示这些权限请求即时你事实上并没有去申请它们。为了避免这种情况,可以移除你不需要的默认权限,比且尽可能的更新你的targetSdkVersion 到最高版本。你可以在Build.VERSION_CODES 文档查看每次发布新版本时添加了哪些权限。

Declaring and Enforcing Permissions
权限的声明和使用

To enforce your own permissions, you must first declare them in your AndroidManifest.xml using one or more < permission> tags.
想要使用你拥有的权限,首先应该在AndroidManifest.xml中通过< permission> 标签声明它们。

For example, an application that wants to control who can start one of its activities could declare a permission for this operation as follows:
例如一个应用程序想要对谁可以启动他的activity进行管理,可以参照下面的操作声明一个权限:

<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>

The < protectionLevel> attribute is required, telling the system how the user is to be informed of applications requiring the permission, or who is allowed to hold that permission。
< protectionLevel>属性是必须项,用来告知系统以怎样的方式让用户获知应用请求的权限,和允许谁持有这个权限。

The < permissionGroup> attribute is optional, and only used to help the system display permissions to the user. You will usually want to set this to either a standard system group (listed in android.Manifest.permission_group) or in more rare cases to one defined by yourself. It is preferred to use an existing group, as this simplifies the permission UI shown to the user.
< permissionGroup>属性是可选的,只用于帮助系统把权限显示给用户。你通常会设置它为你标准系统组(在android.Manifest.permission_group之中列出的),少数情况下你也可以自定义组。要优先使用已经存在的组,这会简化显示给用户的权限UI。

Note that both a label and description should be supplied for the permission. These are string resources that can be displayed to the user when they are viewing a list of permissions (android:label) or details on a single permission ( android:description). The label should be short, a few words describing the key piece of functionality the permission is protecting. The description should be a couple sentences describing what the permission allows a holder to do. Our convention for the description is two sentences, the first describing the permission, the second warning the user of what bad things can happen if an application is granted the permission.
注意,声明权限的时候还需要label和description属性。它们是用于当用户浏览权限列表(android:label)或者单个权限( android:description)的时候的用于显示给用户的字符串资源。label应该尽可能的短,用少量的文字描述依赖于这个权限的关键功能。description 应该是一对描述该权限允许持有者做什么事的语句。人们约定description 有两个句子,第一句描述权限,第二句警告用户,当应用被授予了该权限可能会做什么坏事。

Here is an example of a label and description for the CALL_PHONE permission:
这里有一个CALL_PHONE 权限的label和description例子:

 <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>
         <!---直接拨打电话->
          <!---允许用于在美誉你的干预的情况下拨打电话,恶意应用可能会产生异常的通话记录,注意,这并不会允许该应用去拨打紧急电话。->

You can look at the permissions currently defined in the system with the Settings app and the shell command adb shell pm list permissions. To use the Settings app, go to Settings > Applications. Pick an app and scroll down to see the permissions that the app uses. For developers, the adb ‘-s’ option displays the permissions in a form similar to how the user will see them:
你可以使用设置或者adb shell 命令 adb shell pm list permissions来查看相同中当前的权限定义。使用设置,打开 设置 ->应用程序,下拉然后选中这个应用用到的权限。而对于开发者,使用‘-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

...

Enforcing Permissions in AndroidManifest.xml
在AndroidManifest.xml中执行权限

High-level permissions restricting access to entire components of the system or application can be applied through your AndroidManifest.xml. All that this requires is including an android:permission attribute on the desired component, naming the permission that will be used to control access to it.

可以使用AndroidManifest.xml中的高级权限来限制访问完整的系统组件或者其他应用。
你想要的组件的所有的权限需求都包含在一个 android:permission属性中。指定的权限将管理对它的访问。

Activity permissions (applied to the < activity> tag) restrict who can start the associated activity. The permission is checked during Context.startActivity() and Activity.startActivityForResult(); if the caller does not have the required permission then SecurityException is thrown from the call.
Activity权限(使用< activity>标签)对谁可以访问相应的Activity进行限制。权限将会在Context.startActivity()和Activity.startActivityForResult()时进行检查。如果调用者没有这个权限将会抛出SecurityException。

Service permissions (applied to the tag) restrict who can start or bind to the associated service. The permission is checked during Context.startService(), Context.stopService() and Context.bindService(); if the caller does not have the required permission then SecurityException is thrown from the call.
Service 权限(使用< service>标签)对谁可以启动或者绑定相应的service进行限制。权限将会在Context.startService(),Context.stopService()和Activity.startActivityForResult()时进行检查。

BroadcastReceiver permissions (applied to the < receiver> tag) restrict who can send broadcasts to the associated receiver. The permission is checked after Context.sendBroadcast() returns, as the system tries to deliver the submitted broadcast to the given receiver. As a result, a permission failure will not result in an exception being thrown back to the caller; it will just not deliver the intent. In the same way, a permission can be supplied to Context.registerReceiver() to control who can broadcast to a programmatically registered receiver. Going the other way, a permission can be supplied when calling Context.sendBroadcast() to restrict which BroadcastReceiver objects are allowed to receive the broadcast (see below).
BroadcastReceiver权限(使用< receiver>标签),对谁可以发送相应的广播进行限制。当Context.sendBroadcast() 返回后进行权限检查,由于系统尝试性的发送广播给接收器,因此,权限检查失败不会从调用者抛出异常。这只会不交付于intent。同样的,权限也不能支持Context.registerReceiver()去管理谁可以发送广播给一个动态注册的接收器。其他情况下,权限可以在调用Context.sendBroadcast()限制允许哪个接收器对象去接受广播(见下文)。

ContentProvider permissions (applied to the tag) restrict who can access the data in a ContentProvider. (Content providers have an important additional security facility available to them called URI permissions which is described later.) Unlike the other components, there are two separate permission attributes you can set: android:readPermission restricts who can read from the provider, and android:writePermission restricts who can write to it. Note that if a provider is protected with both a read and write permission, holding only the write permission does not mean you can read from a provider. The permissions are checked when you first retrieve a provider (if you don’t have either permission, a SecurityException will be thrown), and as you perform operations on the provider. Using ContentResolver.query() requires holding the read permission; using ContentResolver.insert(), ContentResolver.update(), ContentResolver.delete() requires the write permission. In all of these cases, not holding the required permission results in a SecurityException being thrown from the call.
ContentProvider 权限(使用 < provider> 标签)对谁可以访问ContentProvider中的数据进行限制。(ContentProvider以一个非常重要的额外安全机制叫做URI permissions,稍后会做描述。)不同于其他组件,这里有两个分开的权限属性,你可以设置 android:readPermission 显示谁可以读取provider,android:writePermission 则限制谁可以写入。注意,如果一个provider 同时被读写权限保护,只有写权限不意味着你可以从读取provider内容,这个权限将会在你第一次检索provider的时候进行检查(如果你没有任何一个权限(读写),将会抛出SecurityException ),和当你对provider执行操作的时候。使用ContentResolver.query()需要持有读权限,ContentResolver.insert(), ContentResolver.update(), ContentResolver.delete()则需要写权限。其他情况下,没有需要的权限将会由调用者抛出一个SecurityException 。

Enforcing Permissions when Sending Broadcasts
当发送广播的时候执行权限

In addition to the permission enforcing who can send Intents to a registered BroadcastReceiver (as described above), you can also specify a required permission when sending a broadcast. By calling Context.sendBroadcast() with a permission string, you require that a receiver’s application must hold that permission in order to receive your broadcast.

当添加一个谁可以发送Intent来注册BroadcastReceiver 的权限的时候,你也可以指定一个发送broadcast的权限需求。通过调用Context.sendBroadcast() 和一个权限字符参数,这样就需要接收器所在的应用持有你注册时定义的权限。

Note that both a receiver and a broadcaster can require a permission. When this happens, both permission checks must pass for the Intent to be delivered to the associated target.
注意,receiver 和broadcaster 都可以添加权限。当这样做时,Intent被交付给相应的目标的时候都需要通过权限检查。

Other Permission Enforcement
其他权限的执行

Arbitrarily fine-grained permissions can be enforced at any call into a service. This is accomplished with the Context.checkCallingPermission() method. Call with a desired permission string and it will return an integer indicating whether that permission has been granted to the current calling process. Note that this can only be used when you are executing a call coming in from another process, usually through an IDL interface published from a service or in some other way given to another process.
任意细粒化的权限都可以在调用service时执行。这通过 Context.checkCallingPermission() 来完成。调用时传入期望的权限字符串,这样会返回一个int来表明当前的调用进程是否有权限。注意,这这只能在当你执行对其他进程的调用的时候使用。通常情况下从service 一个通过一个IDL接口发布,然后用相同的方法在另一个进程获取。

There are a number of other useful ways to check permissions. If you have the pid of another process, you can use the Context method Context.checkPermission(String, int, int) to check a permission against that pid. If you have the package name of another application, you can use the direct PackageManager method PackageManager.checkPermission(String, String) to find out whether that particular package has been granted a specific permission.
这是几个其他用来检查权限的有效方法。如果你有其他进程的pid,你可以使用Context 的方法Context.checkPermission(String, int, int)针对pid来检查权限。如果你有其他应用的包名,你可以直接使用PackageManager 的方法PackageManager.checkPermission(String, String) 来找该包是否存在指定的权限。

URI Permissions
URI权限
The standard permission system described so far is often not sufficient when used with content providers. A content provider may want to protect itself with read and write permissions, while its direct clients also need to hand specific URIs to other applications for them to operate on. A typical example is attachments in a mail application. Access to the mail should be protected by permissions, since this is sensitive user data. However, if a URI to an image attachment is given to an image viewer, that image viewer will not have permission to open the attachment since it has no reason to hold a permission to access all e-mail.
目前的标准权限系统介绍在当你使用content providers时可能并不足够。ontent provider可已用读写权限来保护自己,然而,他的客户端也需要提供特定的URI给其他应用操作。一个典型的例子:邮件应用中的附件。访问邮件动作应该通过权限进行包护。因为这是用户敏感数据。然而,如果一个URI要传递一张附件给一个图片查看器,图片查看器是没有权限打开附件的,因为他没有理由去持有访问所有邮件的权限。

The solution to this problem is per-URI permissions: when starting an activity or returning a result to an activity, the caller can set Intent.FLAG_GRANT_READ_URI_PERMISSION and/or Intent.FLAG_GRANT_WRITE_URI_PERMISSION. This grants the receiving activity permission access the specific data URI in the Intent, regardless of whether it has any permission to access data in the content provider corresponding to the Intent.
per-URI是这个问题的解决方案:当启动Activity或者Activity返回一个结果的时候,调用者可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION 或Intent.FLAG_GRANT_WRITE_URI_PERMISSION(或两种皆有).这会授予接受activity Intent中指定的数据URI 的访问权限。不管怎样,它都有对应的Intent的provider数据的任何访问权限。

This mechanism allows a common capability-style model where user interaction (opening an attachment, selecting a contact from a list, etc) drives ad-hoc granting of fine-grained permission. This can be a key facility for reducing the permissions needed by applications to only those directly related to their behavior.
这种机制允许一种通用能力:在用户与设备点对点的与交互的时候授予设备细粒度的权限。这是减少与应用的行为直接所需要的权限的关键。

The granting of fine-grained URI permissions does, however, require some cooperation with the content provider holding those URIs. It is strongly recommended that content providers implement this facility, and declare that they support it through the android:grantUriPermissions attribute or < grant-uri-permissions> tag.
要实现授予细粒度的URI权限,需要一些持有URIs的provider的配合。极力推推荐在使用provider的时候实现这种机制,可以通过android:grantUriPermissions的属性< grant-uri-permissions> 标签来声明。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值