Android学习笔记6——系统权限

来源:互联网 发布:国内皮鞋品牌 知乎 编辑:程序博客网 时间:2024/05/29 12:05

         Android是一个权限分开的操作系统,每一个应用以不同的系统身份(Linux UserId 和 groupId)运行.系统的每一部分被分割成不同的身份,Linux由此把应用与应用、应用和系统分割开来。

        细化的安全特性被成为Permission的机制所提供,这种机制在某些特定的操作(例如某些特别的进程的处理,URI权限的获取,特定数据的访问等)有着严格的限制。

安全结构:

        android安全结构的一个中心设计理念是默认情况下,没有应用有权限去进行对其他应用、操作系统、或者用户的任何操作。这包括读写用户的私密的数据,读写另一个应用的文件,访问网络,保持设备唤醒状态等等。

       因为每一个Android应用都在一个进程沙漏中运行,应用之间必须明确分享资源和数据。它们依靠声明它们所需要的权限为了扩展这个基础沙漏环境没有提供的功能。应用程序静态的定义声明了他们所需要的权限,这些权限是在被安装时,android系统提醒用户是否允许。Android没有机制能够在运行时动态的获取权限的,因为它严重影响了用户的安全体验。

    然而,应用沙箱并不依靠开发应用的技术,尤其,Dalvik VM并不是一个安全的界限,每个App能够运行Native code。所有类型的应用——Java,native,和hybird以同样的方式被装在沙箱中,彼此之间有着同样的安全等级。

应用签名:

    所有的APK必须被持有在开发者在手中的私有密钥证书签名。这个证书用来鉴定应用的作者,这个证书不需要被权威机构认定,也被允许的。在Android中证书的目的是用来区分应用的作者的,这个证书允许系统获取或者拒绝应用访问重量级的权限和获取或者拒绝另一个拥有相同Linux ID的请求。

用户ID和文件访问:
    在安装的时候,Android系统会自动赋予你的app一个独一无二的用于区别于其他应用的Linux用户ID。这个ID在安装的这个设备上作为常量存在在这个应用的整个生命周期。同一个APP在不同的设备上这个ID可能不一样,更重要的是在同一个给定的设备上,不同的APP的UID必须是不相同的。

   因为安全的执行是在进程级别,任意两个APP的代码不能在同一个进程中运行,因此他们的运行需要拥有不同的Linux UserID作为条件。但是我们可以在每个APP的manifest文件中的manifest标签的用sharedUserId这个属性使得他们拥有相同的UserId。做这些的目的就是使得他们的安全机制把他们当做同一个应用来对待,拥有相同的UserId和文件权限。注意,为了保持安全性,仅仅拥有相同签名的两个应用被给予相同的UserId。

    被存储在应用中的任何数据都会被赋予这个应用的UserId,对于其他的程序是不可正常访问的。但是当我们用geSharedPreferences、openFileOutput、或者openOrCreateDatabase形成一个新文件时,你能够用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE标签让其他的包去访问这个文件。当设置这个标签是,这个文件仍然属于这个应用,但是它的全局的读写权限已经被设置,因此任何其他的程序都能够访问它。

用户权限:

        一个最初的应用程序默认的没有任何权限,这也就意味着它不能做任何损害用户体验的行为或者访问设备上的任何数据。为了充分利用设备上的被保护的功能,你必须在你的应用程序的Manifest文件中包含一个或者更多个定义你的应用程序所需的权限的<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>
        在应用程序被安装的时候,依据在这个应用程序中被签名定义的权限或者用户授权就被应用安装器赋予了。当程序运行是不会检查用户权限,这个app要么在安装的时候获取一个指定的用户权限,这样我们能够使用它,要么没有获取这个权限,任何试图用这个功能的都将失败,并且不需要提示用户。

      很多时候,一个权限的调用失败就会导致应用程序抛出一个SecurityException异常,然而并不是每一个权限调用的失败都会抛出一个异常的。例如,sendBroadcast(Intent)方法在这个方法调用被返回的之后,当数据被发送到每一个接受者的时候才会检查权限,因此在权限调用失败的时候,你不会收到一个异常。然而,大都数情况下,权限异常会被打印到系统日志当中。

     然而,在正常的用户情况下(例如,在app从Google Play store安装),如果一个应用程序没有获取到这个应用所需的全部权限,他是不会被安装到设备上的。因此你不需要担心由于权限的丢失而引起的运行时错误,因为一个应用被安装成功就代表了你的应用获得了它所期待的全部权限。

    Android系统所提供的全部权限都能在Manifest.permission中被找到。任何权限都能被定义并且成为他自己的权限,这个文件并不是一个全部权限的综合列表。

   在你的程序运行的时候一个特殊的权限能够在很多地方执行:

  1、当系统来电话的时候,为了阻止一个应用程序执行正常的功能;

  2、当开启一个Activity时候,阻止运行其他的应用程序的开启;

  3、在发送和接受广播,控制谁能接受你的广播,谁能给你发送广播;

  4、绑定或者开启一个Service;

自定义权限:

为了使用你自己的权限,你必须首先在你的应用程序的Manifest文件中用一个或者几个<permission>标签定义他们。

例如,想要控制一个谁能启动它自己的一个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>
这个protectLevel属性被要求,作用是告诉系统用户怎样通知应用程序请求这个权限,或者谁被允许持有这个权限。

而permissionGroup这个权限是可选的,仅仅被用来帮助系统展示权限给用户,你通常想要把这个设置为要么是一个标准的系统组(在android.Manifest.permission_group中列举出来)或者要么更多的是自己定义的权限。它偏向于用一个存在的分组,因为这样能够简单的展示给用户一个权限的UI。

注意lable和description应该被提供。这些字符资源能够在他们正在看权限列表的时候或者一个权限明细的时候展示给用户。这个lable应该是短的,简单几个单词描述出这个权限的功能,而这个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>
你能用Settings应用查看当前当前定义在系统里的权限,shell命令adb shell pm list permissions为了使用Setting APP,到Setting->Applications。选择一个APP,滚动到最下方这个app所使用的权限,对于开发者来说,adb -s以一种表格的方式展示权限:
$ adb shell pm list permissions -s
在Meanifest文件中使用权限:

高等级的权限严格限制访问系统或者应用的Manfest文件中中应用的全部组件所有的这些要求被包含在<android:permisson>属性中,命名被用来控制访问权限。

Activity的权限严格控制了谁能够开启这个相关的权限。这个权限检查发生在 Context.startActivity() Activity.startActivityForResult()被调用的时候,如果调用者没有所要求的权限,一个异常Security将要抛出;同理Service在Context.startService(), Context.stopService()Context.bindService()被调用的时候检查权限,无权限抛出异常;BroadcastReceiver权限是在Context.sendBroadcast()调用返回后检查,因此当权限调用失败时不会抛出异常,仅仅是不会发送这个Intent,我们也可以动态在程序中用 Context.registerReceiver()控制谁能够发送广播到一个程序注册的接收器;ContentProvider的权限严格控制了谁能访问在ContentProvider中的数据,但是它不像其他的组件,它有两个权限:读权限和写权限,当我们第一次得到一个Provider的时候检查权限,如果没有权限就会抛出异常,ContentResolver.query()需要读权                   限, ContentResolver.insert(),ContentResolver.update(), ContentResolver.delete()需要写权限,所有的这些,在没有权限的情况下都会抛出SecurityException异常.


0 0
原创粉丝点击