android权限管理
来源:互联网 发布:java乘法函数 编辑:程序博客网 时间:2024/06/06 04:20
系统权限
Android 是一个权限分隔的操作系统,其中每个应用都有其独特的系统标识(Linux 用户 ID 和组 ID)。系统各部分也分隔为不同的标识。Linux 据此将不同的应用以及应用与系统分隔开来。
安全架构
在默认情况下,任何应用都没有权限执行对其他应用、操作系统或用户有不利影响的任何操作。比如:读写用户私有数据、执行网络访问等。
Android应用都在进程沙盒中运行,如需访问沙盒外的额外功能,应用应该静态声明所需权限,android系统提示用户同意。
用户 ID 和文件访问
在android系统上,每个应用是一个Linux用户,他们都拥有唯一一个用户ID。应用程序的数据只能被拥有该应用程序对应的用户ID的程序在可以访问,为此,我们可以通过设置AndroidManifest.xml 的 manifest 标记中使用 sharedUserId 属性,以及和该应用程序打相同的签名来共享用户ID,以实现共享数据的功能。在android也可以通过ContentProvider提供数据给其他应用访问。
UserId不同时:
包名不同:未设定process属性时,各自的Activity在各自的进程。 即使process指定了包名,也不会和另一个用户的同名包共享进程。
包名相同:签名相同:覆盖旧的同包名apk。
签名不同:新的apk会安装失败。
UserId相同时:
包名不同:未设定process属性时,各自的Activity在各自的进程。
process属性指定,则可以共享进程。
包名相同:签名相同:覆盖旧的同包名apk。
签名不同:新的apk会安装失败。
使用权限
在android应用中,要利用受保护的设备功能,必须在清单文件中包含一个或者多个<uses-permission>标记。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.app.myapp" > <uses-permission android:name="android.permission.RECEIVE_SMS" /> ...</manifest>
在清单文件中列出的权限,如果是正常权限(不涉及用户隐私数据和设备正常运行)系统自动授予该权限,危险权限(涉及用户隐私数据和正常运行),需要系统通知用户并获得用户同意。
自动权限调整
随着时间的推移,一些特定API的访问,低版本不需要的权限,在高版本API Level中可能需要添加相关权限。Android 将根据为 targetSdkVersion 属性提供的值决定应用是否需要权限。如果该值低于在其中添加权限的版本,则 Android 会自动添加该权限。
例如,API Level 4 中加入了 WRITE_EXTERNAL_STORAGE 权限,用以限制访问共享存储空间。如果您的 targetSdkVersion 为 3 或更低版本,则会向更新 Android 版本设备上的应用添加此权限。
注意:如果某权限自动添加到应用,则即使您的应用可能实际并不需要这些附加权限,Google Play 上的应用列表也会列出它们。
正常权限和危险权限
正常权限涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域,不需要用户授予,系统自动授予。
危险权限涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域,需要系统通知用户,用户授予。
权限组
正常权限和危险权限都是属于权限组,如果设备运行的是 Android 6.0(API 级别 23),targetSdkVersion 是23 或者更高版本:
如果应用请求其清单中列出的危险权限,而应用目前在权限组中没有任何权限,则系统会向用户显示一个对话框,描述应用要访问的权限组。对话框不描述该组内的具体权限。例如,如果应用请求 READ_CONTACTS 权限,系统对话框只说明该应用需要访问设备的联系信息。如果用户批准,系统将向应用授予其请求的权限。
如果应用请求其清单中列出的危险权限,而应用在同一权限组中已有另一项危险权限,则系统会立即授予该权限,而无需与用户进行任何交互。例如,如果某应用已经请求并且被授予了 READ_CONTACTS 权限,然后它又请求 WRITE_CONTACTS,系统将立即授予该权限。
如果设备运行的是 Android 5.1(API 级别 22)或更低版本,并且应用的 targetSdkVersion 是 22 或更低版本,则系统会在安装时要求用户授予权限。再次强调,系统只告诉用户应用需要的权限组,而不告知具体权限。
表 1. 危险权限和权限组。
权限组
权限
CALENDAR
· READ_CALENDAR
· WRITE_CALENDAR
CAMERA
· CAMERA
CONTACTS
· READ_CONTACTS
· WRITE_CONTACTS
· GET_ACCOUNTS
LOCATION
· ACCESS_FINE_LOCATION
· ACCESS_COARSE_LOCATION
MICROPHONE
· RECORD_AUDIO
PHONE
· READ_PHONE_STATE
· CALL_PHONE
· READ_CALL_LOG
· WRITE_CALL_LOG
· ADD_VOICEMAIL
· USE_SIP
· PROCESS_OUTGOING_CALLS
SENSORS
· BODY_SENSORS
SMS
· SEND_SMS
· RECEIVE_SMS
· READ_SMS
· RECEIVE_WAP_PUSH
· RECEIVE_MMS
STORAGE
· READ_EXTERNAL_STORAGE
· WRITE_EXTERNAL_STORAGE
定义和实施权限
一、定义权限
在AndroidManifest.xml 定义一个或多个<permission>权限。例如:
<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>
android:description:对权限的描述,一般是两句话,第一句话描述这个权限所针对的操作,第二句话告诉用户授予app这个权限会带来的后果
android:permissionGroup:权限所属权限组的名称,是可选属性,只是用于帮助系统向用户显示权限。大多数情况下,您要将此设为标准系统组(列在android.Manifest.permission_group 中),但您也可以自己定义一个组。建议使用现有的组,因为这样可简化向用户显示的权限 UI。
android:protectionLevel:权限的等级,
normal是最低的等级,声明此权限的app,系统会默认授予此权限,不会提示用户。
dangerous权限对应的操作有安全风险,系统在安装声明此类权限的app时会提示用户。
signature权限表明的操作只针对使用同一个证书签名的app开放。
signatureOrSystem与signature类似,只是增加了rom中自带的app。(系统app)。
注:系统不允许多个软件包使用同一名称声明权限,除非所有软件包都使用同一证书签署。如果软件包声明权限,则系统不允许用户安装具有相同权限名称的其他软件包,除非这些软件包使用与第一个软件包相同的证书签署。为避免命名冲突,建议对自定义权限使用相反域名样式命名,例如com.example.myapp.ENGAGE_HYPERSPACE。
一、实施权限
如果你开发一套只在自己设备上运行的应用,那可以开发出一个管理权限的软件包,各个应用之间的调用可以通过<uses-permission> 元素请求这些权限。
如果应用的调用和被调用方仅适用于相同的签名才可以,那就可以采用验证签名的方式,而不需要自定义权限。
多个不同签名的应用互相调用,尽可能每个权限只定义一次,多个相同签名的应用也是如此。
实施 AndroidManifest.xml 中的权限
可能在程序运行期间的多个位置实施特定权限:
在调用系统时,防止应用执行某些功能。
在启动 Activity 时,防止应用启动其他应用的 Activity。
在发送和接收广播时,控制谁可以接收您的广播,谁可以向您发送广播。
在访问和操作内容提供程序时。
绑定至服务或启动服务。
Activity权限:在定义Activtiy中设置权限,在startActivity和startActvitiyForResult调用时检查权限,没有权限将会抛出SecurityException。
Service权限:限制谁可以启动或者绑定该Service。在 Context.startService()、Context.stopService() 和 Context.bindService() 时会检查权限;如果调用方没有所需的权限,则调用会抛出 SecurityException。
BroadcastReceiver 权限:限制谁可以发送广播给相关的接收方。在 Context.sendBroadcast() 返回后检查权限,因为系统会尝试将提交的广播传递到指定的接收方。因此,权限失效不会导致向调用方抛回异常;只是不会传递该 intent。同样,可以向 Context.registerReceiver() 提供权限来控制谁可以广播到以编程方式注册的接收方。另一方面,可以在调用 Context.sendBroadcast() 时提供权限来限制允许哪些 BroadcastReceiver 对象接收广播。
ContentProvider 权限:限制谁可以访问 ContentProvider 中的数据。与其他组件不同,您可以设置两个单独的权限属性:android:readPermission 限制谁可以读取提供程序,android:writePermission 限制谁可以写入提供程序。请注意,如果提供程序有读取和写入权限保护,仅拥有写入权限并不表示您可以读取提供程序。第一次检索提供程序时将会检查权限(如果没有任何权限,将会抛出 SecurityException),对提供程序执行操作时也会检查权限。使用 ContentResolver.query() 需要拥有读取权限;使用 ContentResolver.insert()、ContentResolver.update()、ContentResolver.delete() 需要写入权限。在所有这些情况下,没有所需的权限将导致调用抛出 SecurityException。
通常,权限失效会导致 SecurityException 被扔回应用。但不能保证每个地方都是这样。例如,sendBroadcast(Intent) 方法在数据传递到每个接收者时会检查权限,在方法调用返回后,即使权限失效,您也不会收到异常。但在几乎所有情况下,权限失效会记入系统日志。
发送广播时实施权限
除了实施谁可以向注册的 BroadcastReceiver 发送 intent 的权限(如上所述),您还可以指定在发送广播时需要的权限。通过使用权限字符串调用 Context.sendBroadcast(),您可以要求接收方的应用必须拥有该权限才可接收您的广播。
请注意,接收者和广播者可能需要权限。此时,这两项权限检查都必须通过后方可将 intent 传递到相关的目标。
其他权限实施
可对任何服务调用实施任意细化的权限。这可通过Context.checkCallingPermission() 方法完成。使用所需的权限字符串调用,它将返回一个整数,表示权限是否已授予当前的调用进程。请注意,仅在执行从另一个进程传入的调用(通常是通过从服务发布的 AIDL 或者指定给另一进程的某种其他方式完成)时才可使用此方法。
检查权限还有许多其他有用的方法。如果您有另一个进程的 pid,可以使用 Context 方法Context.checkPermission(String, int, int) 检查针对该 pid 的权限。如果您有另一个应用的软件包名称,可以使用直接的 PackageManager 方法PackageManager.checkPermission(String, String) 了解是否已为特定软件包授予特定权限。// 检查调用者是否具有 permission权限 // 此方法仅在调用IPC(interprocess communication)方法时有用 public static boolean checkPermission(Context context, String permission) { //检查如果是当前应用则返回真 if (Binder.getCallingPid() == Process.myPid()) { return true; } if (context.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { return true; } return false; }
判断本程序是否拥有某权限的方法:
private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE"; private static boolean hasExternalStoragePermission(Context context) { int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION); return perm == PackageManager.PERMISSION_GRANTED; }
判断某个程序是否拥有某权限的方法:
private static boolean checkPermission(Context context, String permName, String pkgName){ PackageManager pm = context.getPackageManager(); if(PackageManager.PERMISSION_GRANTED == pm.checkPermission(permName, pkgName)){ System.out.println(pkgName + "has permission : " + permName); return true; }else{ //PackageManager.PERMISSION_DENIED == pm.checkPermission(permName, pkgName) System.out.println(pkgName + "not has permission : " + permName); return false; } }
URI 权限
到目前为止所述的是标准权限系统,内容提供程序仅仅使用此系统通常是不够的。内容提供程序可能需要通过读取和写入权限保护自己,而其直接客户端也需要将特定 URI 传给其他应用以便于它们运行。邮件应用中的附件是一个典型的示例。应通过权限保护对邮件的访问,因为这是敏感的用户数据。但是,如果将图像附件的 URI 提供给图像查看程序,该图像查看程序不会有打开附件的权限,因为它没有理由拥有访问所有电子邮件的权限。
此问题的解决方法是采用 per-URI 权限机制:在启动 Activity 或返回结果给 Activity 时,调用方可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION 和/或Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这将授予接收 Activity 权限访问 intent 中的特定数据 URI,而不管它是否具有访问 intent 对应的内容提供程序中数据的任何权限。此机制支持常见的能力式模型,其中用户交互(打开附件、从列表中选择联系人等)驱动临时授予细化的权限。这是一项关键功能,可将应用所需的权限缩小至只与其行为直接相关的权限。但授予细化的 URI 权限需要与拥有这些 URI 的内容提供程序进行一定的合作。强烈建议内容提供程序实施此功能,并且通过 android:grantUriPermissions 属性或<grant-uri-permissions> 标记声明支持此功能。详细使用信息见:URI权限
- android权限管理大全
- Android权限管理
- Android应用程序权限管理
- android权限管理
- Android 读取权限管理
- Android权限管理
- android 6.0权限管理
- Android 6.0权限管理
- Android 6.0权限管理
- android 6.0权限管理
- Android M权限管理
- 吐槽 Android 权限管理
- Android Studio权限管理
- Android 6.0 权限管理
- Android应用程序权限管理
- Android 6.0 权限管理
- Android 权限管理
- Android 6.0 权限管理
- ECharts.js学习(二)动态数据绑定
- SSM框架搭建
- BZOJ 3172: [Tjoi2013]单词 AC自动机/后缀自动机
- springmvc创建导出视图
- 取值方法
- android权限管理
- 88. Merge Sorted Array
- PHPCMS 配置支付宝接口
- 面试OR笔试13——字母数字排序
- c++ 常用STL笔记
- xpath与多线程爬虫
- 设计模式——享元模式
- 算法系列——数组中出现次数超过一半的数字(剑指offer)
- miniui datagrid 创建表格