Android6.0运行时权限学习

来源:互联网 发布:linux 使用socket通信 编辑:程序博客网 时间:2024/06/13 07:16

Android6.0运行时权限学习

通过查看android开发者文档。

系统权限

Android 是一个权限分隔的操作系统,其中每个应用都有其独特的系统标识(Linux 用户 ID 和组 ID)。系统各部分也分隔为不同的标识。Linux 据此将不同的应用以及应用与系统分隔开来。

其他更详细的安全功能通过“权限”机制提供,此机制会限制特定进程可以执行的具体操作,并且根据 URI 权限授权临时访问特定的数据段。

本文档介绍应用开发者可以如何使用 Android 提供的安全功能。一般性的 Android 安全性概览在“Android 开源项目”中提供。

安全架构

Android 安全架构的中心设计点是:在默认情况下任何应用都没有权限执行对其他应用、操作系统或用户有不利影响的任何操作。这包括读取或写入用户的私有数据(例如联系人或电子邮件)、读取或写入其他应用程序的文件、执行网络访问、使设备保持唤醒状态等。

由于每个 Android 应用都是在进程沙盒中运行,因此应用必须显式共享资源和数据。它们的方法是声明需要哪些权限来获取基本沙盒未提供的额外功能。应用以静态方式声明它们需要的权限,然后 Android 系统提示用户同意。

应用沙盒不依赖用于开发应用的技术。特别是,Dalvik VM 不是安全边界,任何应用都可运行原生代码(请参阅 Android NDK)。各类应用 — Java、原生和混合 — 以同样的方式放在沙盒中,彼此采用相同程度的安全防护。

应用签署

所有 APK(.apk 文件)都必须使用证书签署,其私钥由开发者持有。此证书用于识别应用的作者。证书不需要由证书颁发机构签署;Android 应用在理想情况下可以而且通常也是使用自签名证书。证书在 Android 中的作用是识别应用的作者。这允许系统授予或拒绝应用对签名级权限的访问,以及授予或拒绝应用获得与另一应用相同的 Linux 身份的请求。

用户 ID 和文件访问

在安装时,Android 为每个软件包提供唯一的 Linux 用户 ID。此 ID 在软件包在该设备上的使用寿命期间保持不变。在不同设备上,相同软件包可能有不同的 UID;重要的是每个软件包在指定设备上的 UID 是唯一的。

由于在进程级实施安全性,因此任何两个软件包的代码通常都不能在同一进程中运行,因为它们需要作为不同的 Linux 用户运行。您可以在每个软件包的 AndroidManifest.xml 的 manifest 标记中使用 sharedUserId 属性,为它们分配相同的用户 ID。这样做以后,出于安全目的,两个软件包将被视为同一个应用,具有相同的用户 ID 和文件权限。请注意,为保持安全性,只有两个签署了相同签名(并且请求相同的 sharedUserId)的应用才被分配同一用户 ID。

应用存储的任何数据都会被分配该应用的用户 ID,并且其他软件包通常无法访问这些数据。使用 getSharedPreferences(String, int)、openFileOutput(String, int) 或 openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory) 创建新文件时,可以使用 MODE_WORLD_READABLE 和/或 MODE_WORLD_WRITEABLE 标记允许任何其他软件包读取/写入文件。设置这些标记时,文件仍归您的应用所有,但其全局读取和/或写入权限已适当设置,使任何其他应用都可看见它。

正常权限和危险权限

系统权限分为几个保护级别。需要了解的两个最重要保护级别是正常权限和危险权限:

  • 正常权限涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域。例如,设置时区的权限就是正常权限。如果应用声明其需要正常权限,系统会自动向应用授予该权限。如需当前正常权限的完整列表,请参阅正常权限。

  • 危险权限涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域。例如,能够读取用户的联系人属于危险权限。如果应用声明其需要危险权限,则用户必须明确向应用授予该权限。

权限组

所有危险的 Android 系统权限都属于权限组。如果设备运行的是 Android 6.0(API 级别 23),并且应用的 targetSdkVersion 是 23 或更高版本,则当用户请求危险权限时系统会发生以下行为:
- 如果应用请求其清单中列出的危险权限,而应用目前在权限组中没有任何权限,则系统会向用户显示一个对话框,描述应用要访问的权限组。对话框不描述该组内的具体权限。例如,如果应用请求 READ_CONTACTS 权限,系统对话框只说明该应用需要访问设备的联系信息。如果用户批准,系统将向应用授予其请求的权限。
- 如果应用请求其清单中列出的危险权限,而应用在同一权限组中已有另一项危险权限,则系统会立即授予该权限,而无需与用户进行任何交互。例如,如果某应用已经请求并且被授予了 READ_CONTACTS 权限,然后它又请求 WRITE_CONTACTS,系统将立即授予该权限。
- 任何权限都可属于一个权限组,包括正常权限和应用定义的权限。但权限组仅当权限危险时才影响用户体验。可以忽略正常权限的权限组。

  • 危险权限组.
权限组 权限 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

定义和实施权限

也可以定义自己的权限组和权限,规定那又可以启动activity,service等等,详情见:官方文档


6.0动态权限

从官方文档可以6.0之前获取权限,是在安装时用户确认的。而在6.0之后android的危险权限,需要在运行时动态获取,以弹出框形式提示用户,需要获取权限。

权限获取的时机

应用如果一味要求用户提供授权,可能会让用户无所适从。如果用户发现应用难以使用,或者担心应用会滥用其信息,他们可能不愿意使用该应用,甚至会将其完全卸载。以下最佳做法有助于避免此类糟糕的用户体验。
- 考虑使用Intent:在需要时在提示用户授权。

  • 仅要求您需要的权限

  • 解释需要权限的原因:系统在您调用 requestPermissions() 时显示的权限对话框将说明应用需要的权限,但不会解释为何需要这些权限。某些情况下,用户可能会感到困惑。因此,最好在调用 requestPermissions() 之前向用户解释应用需要相应权限的原因。

动态权限使用

  • 使用int checkSelfPermisson(String permisson)检查自身的权限

    • permission 将要被检测的权限。
    • 返回值如果有此权限返回PERMISSON_GRANTED,zo否则 PERMISSION_DENIED。
  • 使用void requestPermissions (String[] permissions, int requestCode)系统会弹窗提示是否开启权限。

    • permissions 必须的权限(危险权限)。
    • requestCode 是请求码,随意定义,要大于0。
  • 然后会默认调用void onRequestPermissionsResult (int requestCode, String[] permissions,int[] grantResults)

    • requestCode,之前requestPermission的请求码。
    • 必须的权限。
    • 处理的结果。
  • 使用

        //如果当前的API版本大于等于23,即android6.0        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {            //检查自身是否有定位权限            if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {                requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_LOCATION);            }        }
/**     * 选择是否打开权限后,会调用这里的方法,处理接收或者不接受权限的响应     *     * @param requestCode     * @param permissions     * @param grantResults     */    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        switch (requestCode) {            case REQUEST_CODE_LOCATION:                //做相应的处理                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                    Snackbar.make(getWindow().getDecorView(),"权限处理成功!",Snackbar.LENGTH_SHORT).show();                } else {                    Snackbar.make(getWindow().getDecorView(),"权限处理失败!",Snackbar.LENGTH_SHORT).show();                }                break;        }    }

==小提示:==
- 如果当前程序的targetSdkVersion<23则没有动态权限。
- 如果目标程序是从6.0以下升级到6.0的,程序默认获得危险权限,不用再次动态授权。

0 0
原创粉丝点击