Android开发指南-框架主题-安全和许可

简介: 概述:Android操作系统是一个安全便捷的Linux系统,遵循Linux系统机制,允许多进程。为了进程间的数据共享和交互共用,设计“权限”这个名词,声明权限代表可使用此权限,未声明则一般不能使用。


概述:Android操作系统是一个安全便捷的Linux系统,遵循Linux系统机制,允许多进程。为了进程间的数据共享和交互共用,设计“权限”这个名词,声明权限代表可使用此权限,未声明则一般不能使用。共用有系统级别的数据,也有进程间的数据,可以用在Sqlite,可以用在Android四大控件:Activity、Service、BroadCast Receiver、ContentProvider,支持自定义权限,详见:Android自定义权限和使用权限

安全和许可Security and Permissions

    Android是一个多进程系统,每个应用程序(以及系统的部分)运行在它自己的进程里。大多数程序和系统之间的安全性通过基础的Linux机制在进程级别进行支持,如分配给应用程序的用户和群组IDs。更多细化的安全特性通过“许可”机制来提供,它实施对一个进程能够执行的特定操作方面的限制,和对于每个URI的特定数据段的特许访问的授权。

 

安全架构Security Architecture

    Android安全架构中的一个设计要点是在默认情况下应用程序没有权限执行对其它应用程序、操作系统或用户有害的操作这些操作包括读/写用户的隐私数据(例如联系方式或e-mail),读/写其它应用程序的文件,执行网络访问,保持设备激活,等等

    应用程序的进程是一个安全的沙箱。它不能干扰其它应用程序,除非明确声明它需要额外的基本的沙箱不能提供的功能的许可权。这些许可权请求能够被不同方式的操作所处理,常见的是基于证书和用户提示的自动允许或禁止。应用程序的权限请求被声明为静态的,这样后面在安装时能够知道它们而且不会被改变。

 

应用程序签名Application Signing

    所有的Android应用程序(.apk文件)必须用证书进行签名认证,而这个证书的私钥是由开发者保有的。该证书可以用以识别应用程序的作者。该证书也不需要被认证机构签名。Android应用程序完全允许而且一般也都是使用自签名(self-signed)证书。证书是用于在应用程序之间建立信任关系,而不是用于控制程序是否可以安装。签名影响安全性的最重要的方式是通过决定谁可以进入基于签名的许可,以及谁可以共享用户IDs。

 

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

    每一个Android应用程序(.apk文件)都会在安装时就分配一个独有的Linux用户ID,这就为它建立了一个沙盒,使其不能与其他应用程序进行接触(也不会让其它应用程序接触它)。这个用户ID会在安装时分配给它,并在该设备上一直保持同一个数值。

    由于安全性限制措施是发生进程级,所以两个package中的代码不会运行在同一个进程当中,他们要作为不同的Linux用户出现。我们可以通过使用AndroidManifest.xml文件中的manifest标签中的sharedUserId属性,来使不同的package共用同一个用户ID。通过这种方式,这两个package就会被认为是同一个应用程序,拥有同一个用户ID(实际不一定),并且拥有同样的文件存取权限。注意:为了保持安全,只有当两个应用程序被同一个签名签署的时候(并且请求了同一个sharedUserId)才会被分配同样的用户ID.

    所有存储在应用程序中的数据都会赋予一个属性-该应用程序的用户ID,这使得其他package无法访问这些数据。当通过这些方法getSharedPreferences(String, int), openFileOutput(String, int), 或者openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory)来创建一个新文件时,你可以通过使用MODE_WORLD_READABLE与/或MODE_WORLD_WRITEABLE标志位来设置是否允许其他package来访问读写这个文件。当设置这些标志位时,该文件仍然属于该应用程序,但是它的全局读写权限已经被设置,使得它对于其他任何应用程序都是可见的。

 

使用许可Using Permissions

    一个基本的Android程序通常是没有任何许可与之关联的,这就是说它不能做任何扰乱用户或破坏数据的勾当。那么为了使用设备被保护的特性,我们就必须在AndroidManifest.xml添加一个或多个<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>

   在应用程序安装时,该应用程序请求的权限许可是通过package installer来授予的。package installer是通过检查该应用程序的签名和/或用户的交换结果来确定是否给予该程序request的权限。在用户使用过程中不会去检查权限,也就是说要么在安装的时候就批准该权限,使其按照设计可以使用该权限;要么就不批准,这样用户也就根本无法使用该feature,也不会有任何提示告知用户尝试失败。

    很多时候, 一个许可失败会导致一个SecurityException被抛回该应用程序. 但是Android并不保证这种情况会处处发生。例如,当数据被deliver到每一个receiver的时候,sendBroadcast(Intent) 方法会去检查permissions,在这个方法调用返回之后,你也不会收到任何exception。几乎绝大多数情况,一个permission failure都会打印到log当中。(注意查看Logcat)

    Android系统定义的权限可以在Manifest.permission类中找到。任何一个程序都可以定义并强制执行自己独有的permissions,因此Manifest.permission中定义的permissions并不是一个完整的列表(即有肯能有自定义的permissions)。

一个特定的许可可能会在你的程序操作过程中的很多地方都被实施:

  • 当系统有来电的时候,用以阻止程序执行其它功能。
  • 当启动一个活动(activity)的时候,会阻止应用程序启动其它应用程序的Acitivity。
  • 在发送和接收广播的时候,去控制谁可以接收你的广播或谁可以发送广播给你。
  • 当进入并操作一个内容提供器(content provider)的时候
  • 当绑定或起动一个服务(service)的时候
 

声明和实施许可Declaring and Enforcing Permissions

    为了实施你自己的permissions,你必须首先在AndroidManifest.xml文件中声明该permissions.通常我们通过使用一到多个<permission> tag来进行声明。

 例如,一个应用程序想要控制谁能启动它的活动,可以为该操作声明许可如下:

<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>属性是可选的,只是用于帮助系统显示许可permission给用户(实际是告知系统该许可是属于哪个许可组permission group的)。你通常会选择使用标准的system group来设定该属性,或者更为少见的用你自己定义的group。推荐使用一个已经存在的group,因为这样UI给用户显示许可的时候会更简单。

需要注意的是标签(label)和描述(description)都是需要为许可提供的。这些都是字符串资源,当用户去看许可列表(android:label)或者某个许可的详细信息(android:description)时,这些字符串资源就可以显示给用户。label应当尽量简短,之需要告知用户该许可是在保护什么功能就行。而description可以用于具体描述获取该许可的程序可以做哪些事情,实际上让用户可以知道如果他们同意程序获取该权限的话,该程序可以做什么。我们通常用两句话来描述许可,第一句描述该许可,第二句警告用户如果批准该权限会可能有什么不好的事情发生。下面是一个描述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>

你可以通过shell指令 adb shell pm list permissions 来查看目前系统已有的permissions. 特别的,"-s"选项会以一种用户会看到的基本相同的格式来显示这些permissions。

 

 在清单文件里实施许可Enforcing Permissions in AndroidManifest.xml

    用于限制进入系统或应用程序的Components的高级别许可可以再AndroidManifest.xml中实现.所有这些都可以通过在相应的component中包含 android:permission 属性,命名该permission以使其被用以控制进入的权限。

    Activity许可(应用于<activity>标签)限制了谁才可以启动相应的活动。permission会在Context.startActivity()和Activity.startActivityForResult()的时候进行检查。如果caller没有所需的权限,则会抛出一个SecurityException。

    Service许可(应用于<service>标签)用于限制谁才可以start或bind该service。在Context.startService() , Context.stopService()和Context.bindService()调用的时候会进行权限检查。如果caller没有所需的权限,则会抛出一个SecurityException。

    BroadcastReceiver许可(应用于<receiver>标签)用于限制谁才可以向该receiver发送广播。权限检查会在Context.sendBroadcast() 返回时进行,由系统去发送已经提交的广播给相应的Receiver。最终,一个permission failure不会再返回给Caller一个exception;它只是不会去deliver该Intent而已。同样地,Context.registerReceiver()也可以有自己permission用于限制谁才可以向一个在程序中注册的receiver发送广播。另一种方式是,一个permission也可以提供给Context.sendBroadcast() 用以限制哪一个BroadcastReceiver才可以接收该广播。

    ContentProvider许可(应用于<provider>标签)用于限制谁才可以访问ContentProvider提供的数据。(Content providers有一套而外的安全机制叫做URI permissions,这些在稍后讨论)不同于其它的Components,这里有两种不同的permission属性可以设置: android:readPermission 用于限制谁可以读取provider中的数据,而 android:writePermission 用于限制谁才可以向provider中写入数据。需要注意的是如果provider同时被读写许可,如果这时只有写许可并不意味着你就可以读取provider中的数据了。当你第一次获取provider的时候就要进行权限检查(如果你没有任何permission,则会抛出SecurityException), 并且这时你对provider执行了某些操作。当使用ContentResolver.query()时需要读权限,而当使用ContentResolver.insert(), ContentResolver.update(), ContentResolver.delete()时需要写权限。在所有这些情况下,没有所需的permission将会导致SecurityException被抛出。

 

发送广播时实施许可Enforcing Permissions when Sending Broadcasts

    除了之前说过的Permission(用于限制谁才可以发送广播给相应的BroadcastReceiver),你还可以在发送广播的时候指定一个permission。在调用Context.sendBroadcast()的时候使用一个permission string,你就可以要求receiver的宿主程序必须有相应的permission。

    值得注意的是Receiver和broadcaster都可以要求permission。当这种情况发生时,这两种permission检查都需要通过后才会将相应的intent发送给相关的目的地。

 

其他权限实施Other Permission Enforcement

    在调用service的过程中可以设置任意细化的许可。这是通过Context.checkCallingPermission()方法来完成的。呼叫的时候使用一个想得到的permission string,并且当该权限获批的时候可以返回给呼叫方一个Integer(没有获批也会返回一个Integer)。需要注意的是这种情况只能发生在来自另一个进程的呼叫,通常是一个service发布的IDL接口或者是其他方式提供给其他的进程。

    Android提供了很多其他的方式用于检查permissions。如果你有另一个进程的pid,你就可以通过Context.checkPermission(String, int, int)去针对那个pid去检查permission。如果你有另一个应用程序的package name,你可以直接用PackageManager的方法PackageManager.checkPermission(String, String)来确定该package是否已经拥有了相应的权限。

 

URI许可URI Permissions

    到目前为止我们讨论的标准的permission系统对于内容提供器(content provider)来说是不够的。一个内容提供器可能想保护它的读写权限,而同时与它对应的直属客户端也需要将特定的URI传递给其它应用程序,以便对该URI进行操作。一个典型的例子是邮件应用程序的附件。访问邮件需要使用permission来保护,因为这些是敏感的用户数据。然而,如果有一个指向图片附件的URI需要传递给图片浏览器,那个图片浏览器是不会有访问附件的权利的,因为它不可能拥有所有的邮件的访问权限。

   针对这个问题的解决方案就是per-URI permission: 当启动一个activity或者给一个activity返回结果的时候,呼叫方可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION和/或 Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这赋予接收活动(activity)访问该意图(Intent)指定的URI的权限,而不论它是否有权限进入该意图对应的内容提供器。

    这种机制允许一个通常的能力-风格(capability-style)模型,以用户交互(如打开一个附件, 从列表中选择一个联系人)来驱动细化的特别授权。这是一个很关键的能力,可以减少应用程序所需要的权限,只留下和程序行为直接相关的权限。

    这些URI permission的获取需要内容提供器(包含那些URI)的配合。强烈推荐在内容提供器中实现这种能力,并通过android:grantUriPermissions或者<grant-uri-permissions>标签来声明支持。

    更多的信息可以参考Context.grantUriPermission(), Context.revokeUriPermission()和Context.checkUriPermission()方法。

官方文档原文http://androidappdocs.appspot.com/guide/topics/security/security.html

目录
相关文章
|
2月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
3月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台框架解析
在移动应用开发的广阔舞台上,安卓和iOS一直是两大主角。随着技术的进步,开发者们渴望能有一种方式,让他们的应用能同时在这两大平台上运行,而不必为每一个平台单独编写代码。这就是跨平台框架诞生的背景。本文将探讨几种流行的跨平台框架,包括它们的优势、局限性,以及如何根据项目需求选择合适的框架。我们将从技术的深度和广度两个维度,对这些框架进行比较分析,旨在为开发者提供一个清晰的指南,帮助他们在安卓和iOS的开发旅程中,做出明智的选择。
|
15天前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
81 3
|
23天前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
40 8
|
2月前
|
设计模式 Java Android开发
探索安卓应用开发:从新手到专家的旅程探索iOS开发中的SwiftUI框架
【8月更文挑战第29天】本文旨在通过一个易于理解的旅程比喻,带领读者深入探讨安卓应用开发的各个方面。我们将从基础概念入手,逐步过渡到高级技术,最后讨论如何维护和推广你的应用。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的代码示例。让我们一起开始这段激动人心的旅程吧!
|
2月前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
如何使用Amlogic T972安卓9.0系统上的misc框架来简化驱动程序开发,通过misc框架自动分配设备号并创建设备文件,从而减少代码量并避免设备号冲突。
24 0
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
|
2月前
|
存储 前端开发 Java
Android MVVM框架详解与应用
在Android开发中,随着应用复杂度的增加,如何有效地组织和管理代码成为了一个重要的问题。MVVM(Model-View-ViewModel)架构模式因其清晰的结构和高效的开发效率,逐渐成为Android开发者们青睐的架构模式之一。本文将详细介绍Android MVVM框架的基本概念、优势、实现流程以及一个实际案例。
|
3月前
|
存储 安全 数据安全/隐私保护
🔎Android安全攻防实战!守护你的应用数据安全,让用户放心使用!🛡️
【7月更文挑战第28天】在移动应用盛行的时代,确保Android应用安全性至关重要。本文以问答形式探讨了主要安全威胁(如逆向工程、数据窃取)及其对策。建议使用代码混淆、签名验证、数据加密等技术来增强应用保护。此外,还推荐了加密API、HTTPS通信、代码审计等措施来进一步加强安全性。综上所述,全面的安全策略对于构建安全可靠的应用环境必不可少。#Android #应用安全 #代码混淆 #数据加密
55 3
|
3月前
|
存储 安全 Android开发
安卓应用开发的安全之道
【7月更文挑战第4天】在数字时代,移动应用的安全性至关重要。本文将深入探讨在安卓平台上开发安全应用的最佳实践,包括代码混淆、数据存储加密、网络通信安全、权限管理以及定期的安全审计和更新策略。通过这些措施,开发者可以显著提高他们的应用抵御恶意攻击的能力,保护用户数据免受侵害。
|
3月前
|
前端开发 安全 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
【7月更文挑战第28天】在Android开发领域,五大框架如星辰般指引方向,加速进程,提升应用品质。1. **Retrofit**:Square公司的类型安全HTTP客户端,使网络请求变得优雅简洁。2. **Room**:Google推荐的ORM库,简化SQLite数据库访问。3. **MVVM**:一种架构模式,提高代码可维护性和扩展性。4. **Dagger 2**:依赖注入框架,减少样板代码,以声明方式管理依赖。5. **Jetpack Compose**:全新的UI工具包,采用声明式UI编程,让UI开发更直观高效。掌握这些框架,能有效应对Android开发挑战,助力打造爆款应用。
215 0

相关实验场景

更多
下一篇
无影云桌面