Android開發指南-框架主題-安全和許可

安全和許可Security and Permissionsandroid

Android是一個多進程系統,每一個應用程序(以及系統的部分)運行在它本身的進程裏。大多數程序和系統之間的安全性經過基礎的Linux機制在進程級別進行支持,如分配給應用程序的用戶和羣組IDs。更多細化的安全特性經過「許可」機制來提供,它實施對一個進程可以執行的特定操做方面的限制,和對於每一個URI的特定數據段的特許訪問的受權。shell

安全架構Security Architecture瀏覽器

Android安全架構中的一個設計要點是在默認狀況下應用程序沒有權限執行對其它應用程序、操做系統或用戶有害的操做。這些操做包括讀/寫用戶的隱私數據(例如聯繫方式或e-mail),讀/寫其它應用程序的文件,執行網絡訪問,保持設備激活,等等。安全

應用程序的進程是一個安全的沙箱。它不能干擾其它應用程序,除非明確聲明它須要額外的基本的沙箱不能提供的功能的許可權。這些許可權請求可以被不一樣方式的操做所處理,常見的是基於證書和用戶提示的自動容許或禁止。應用程序的權限請求被聲明爲靜態的,這樣後面在安裝時可以知道它們並且不會被改變。網絡

 

應用程序簽名Application Signing架構

全部的Android應用程序(.apk文件)必須用證書進行簽名認證,而這個證書的私鑰是由開發者保有的。該證書能夠用以識別應用程序的做者。該證書也不須要被認證機構簽名。Android應用程序徹底容許並且通常也都是使用自簽名(self-signed)證書。證書是用於在應用程序之間創建信任關係,而不是用於控制程序是否能夠安裝。簽名影響安全性的最重要的方式是經過決定誰能夠進入基於簽名的許可,以及誰能夠共享用戶IDs。app

用戶IDs和文件訪問User IDs and File Accesside

每個Android應用程序(.apk文件)都會在安裝時就分配一個獨有的Linux用戶ID,這就爲它創建了一個沙盒,使其不能與其餘應用程序進行接觸(也不會讓其它應用程序接觸它)。這個用戶ID會在安裝時分配給它,並在該設備上一直保持同一個數值。this

因爲安全性限制措施是發生進程級,因此兩個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添加一個或多個 標籤,用以聲明你的應用程序須要的許可。

例如,一個想要監控接收短消息的應用程序須要指定:

http://schemas.android.com/apk/res/android"    package="com.android.app.myapp" >     在應用程序安裝時,該應用程序請求的權限許但是經過package installer來授予的。package installer是經過檢查該應用程序的簽名和/或用戶的交換結果來肯定是否給予該程序request的權限。在用戶使用過程當中不會去檢查權限,也就是說要麼在安裝的時候就批准該權限,使其按照設計可使用該權限;要麼就不批准,這樣用戶也就根本沒法使用該feature,也不會有任何提示告知用戶嘗試失敗。

不少時候, 一個許可失敗會致使一個SecurityException被拋回該應用程序. 可是Android並不保證這種狀況會到處發生。例如,當數據被deliver到每個receiver的時候,sendBroadcast(Intent) 方法會去檢查permissions,在這個方法調用返回以後,你也不會收到任何exception。幾乎絕大多數狀況,一個permission failure都會打印到log當中。

Android系統定義的權限能夠在Manifest.permission中找到。任何一個程序均可以定義並強制執行本身獨有的permissions,所以Manifest.permission中定義的permissions並非一個完整的列表(即有肯能有自定義的permissions)。

一個特定的許可可能會在你的程序操做過程當中的不少地方都被實施:

²  當系統有來電的時候,用以阻止程序執行其它功能。

²  當啓動一個活動(activity)的時候,會阻止應用程序啓動其它應用程序的Acitivity。

²  在發送和接收廣播的時候,去控制誰能夠接收你的廣播或誰能夠發送廣播給你。

²  當進入並操做一個內容提供器(content provider)的時候

²  當綁定或起動一個服務(service)的時候

聲明和實施許可Declaring and Enforcing Permissions

爲了實施你本身的permissions,你必須首先在AndroidManifest.xml文件中聲明該permissions.一般咱們經過使用一到多個 tag來進行聲明。

例如,一個應用程序想要控制誰能啓動它的活動,能夠爲該操做聲明許可以下:

http://schemas.android.com/apk/res/android"

    package="com.me.app.myapp" >

 

    < p>

        android:label="@string/permlab_deadlyActivity"

        android:description="@string/permdesc_deadlyActivity"

        android:permissionGroup="android.permission-group.COST_MONEY"

        android:protectionLevel="dangerous" />

 

這裏 屬性是必需的,經過聲明該屬性,咱們就能夠告知系統如何去通知用戶哪些應用程序須要這個許可,或者誰能夠擁有該許可。具體請參看連接的文檔。

屬性是可選的,只是用於幫助系統顯示許可permission給用戶(實際是告知系統該許但是屬於哪一個許可組permission group的)。你一般會選擇使用標準的system group來設定該屬性,或者更爲少見的用你本身定義的group。推薦使用一個已經存在的group,由於這樣UI給用戶顯示許可的時候會更簡單。

須要注意的是標籤(label)和描述(description)都是須要爲許可提供的。這些都是字符串資源,當用戶去看許可列表(android:label)或者某個許可的詳細信息(android:description)時,這些字符串資源就能夠顯示給用戶。label應當儘可能簡短,之須要告知用戶該許但是在保護什麼功能就行。而description能夠用於具體描述獲取該許可的程序能夠作哪些事情,實際上讓用戶能夠知道若是他們贊成程序獲取該權限的話,該程序能夠作什麼。咱們一般用兩句話來描述許可,第一句描述該許可,第二句警告用戶若是批准該權限會可能有什麼很差的事情發生。下面是一個描述CALL_PHONE 許可的label和description的例子:

    directly call phone numbers

    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.

你能夠經過shell指令 adb shell pm list permissions 來查看目前系統已有的permissions. 特別的,"-s"選項會以一種用戶會看到的基本相同的格式來顯示這些permissions:

$ 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

用於限制進入系統或應用程序的Components的高級別許可能夠再AndroidManifest.xml中實現.全部這些均可以經過在相應的component中包含 android:permission 屬性,命名該permission以使其被用以控制進入的權限。

Activity許可(應用於 標籤)限制了誰才能夠啓動相應的活動。permission會在Context.startActivity()和Activity.startActivityForResult()的時候進行檢查。若是caller沒有所需的權限,則會拋出一個SecurityException。

Service許可(應用於 標籤)用於限制誰才能夠start或bind該service。在Context.startService() , Context.stopService()和Context.bindService()調用的時候會進行權限檢查。若是caller沒有所需的權限,則會拋出一個SecurityException。

BroadcastReceiver許可(應用於 標籤)用於限制誰才能夠向該receiver發送廣播。權限檢查會在Context.sendBroadcast() 返回時進行,由系統去發送已經提交的廣播給相應的Receiver。最終,一個permission failure不會再返回給Caller一個exception;它只是不會去deliver該Intent而已。一樣地,Context.registerReceiver()也能夠有本身permission用於限制誰才能夠向一個在程序中註冊的receiver發送廣播。另外一種方式是,一個permission也能夠提供給Context.sendBroadcast() 用以限制哪個BroadcastReceiver才能夠接收該廣播。

ContentProvider許可(應用於 標籤)用於限制誰才能夠訪問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或者 標籤來聲明支持。

更多的信息能夠參考Context.grantUriPermission(), Context.revokeUriPermission()和Context.checkUriPermission()方法。

 

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/iefreer/archive/2009/09/10/4537371.aspx

相關文章
相關標籤/搜索