1. 程式人生 > >Android Permission詳解

Android Permission詳解

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

Android系統構造在Linux系統之上,因此它採用了和Linux型別的許可權隔離機制,也就是說,每個應用使用獨立的系統標識(組標識加使用者標識)來執行。部分系統應用也使用某個系統標識獨立開來。底層的Liunx系統從而使得不同應用之間以及應用和系統之間隔離開來。

Android通過Permission(許可權)機制進一步強化系統安全,通過Permssion來限制某個程序可以執行的操作,為訪問某些特定的資料根據其URIPermissions賦予相應許可權。

系統安全構架

Android系統安全構造的一箇中心設計思想是:預設情況下,應用無權執行可能對其它應用,作業系統或是使用者造成影響的任何操作,這些操作可能包括讀寫使用者個人資料(比如通訊錄或是電子郵件),讀寫其它應用的檔案,訪問網路以及保持設定處於“喚醒”狀態等。

Android系統使用“沙箱”將多個應用分隔開來,因此如有需要,應用必須明確指明需要和其它應用共享的資源或資料。這需要通過申明預設“沙箱”未支援的“Permissions”來獲得這些額外的功能。應用在Manifest檔案中靜態宣告所需許可權,Android系統在安裝應用時會詢問使用者是否賦予該應用所需許可權。為避免使用者決定安全問題的複雜性,Android系統不支援在執行時動態賦予應用所需許可權。

   Android的“沙箱”機制獨立於用來建立應用所使用的技術,尤其要注意的Dalvik虛擬機器不是安全機制的界限,任意應用都可以執行Native程式碼。所有的應用,Java,Native或者是二者的混合,使用同樣的“沙箱”安全機制並具有同等的安全等級。

應用簽名

所有的Android應用(.apk檔案)都必須使用安全證書來簽名,證書的金鑰由開發人員擁有。證書表明應用的開發人員身份。但這個安全證書並不要求是由某個公認的證書管理中心(CA)來簽發。通常開發人員多使用自己簽發的證書。Android使用證書的目的是為了用來區分應用的作者。這使得Android可以據此來賦予或拒絕應用所需的許可權,或者拒絕或者賦予某個應用申請使用其它應用同樣的Linux使用者來執行該應用的請求。

使用者標識和檔案訪問

在安裝應用時,Android為每個安裝包分配不同的Linux使用者標識。這個標識在該安裝包在裝置上整個生命週期時保持一致。在不同的裝置上,這個使用者標誌可能不同,重要的是在同一裝置上,每個安裝包使用不同的使用者標識。

由於Android安全機制是基於程序來賦予的,通常情況下兩個不同的應用程式包使用不的程序來執行,這是因為它們使用了不同的Linux使用者來執行的。你可以通過在AndroidManifest.xml檔案中通過sharedUserId屬性為不同的安裝包指明同一個使用者標識,在這種情況下,這兩個程式包執行在同一程序中,因此使用同樣的安全機制。要注意的這兩個安裝包必須是使用同一個安裝證書來簽名,這樣才能保證足夠的安全機制。

應用程式儲存的資料都會賦予應用使用的使用者標識,通常情況下其它應用無法訪問這些資料。在使用getSharedPreference(String,int), openFileOutput(String,int) 或openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory) 建立檔案時,你可以通過設定MODE_WORLD_READABLE 或MODE_WORLD_WRITEABLE 標誌允許其它應用來讀寫這些檔案。設定了這些標誌,這些檔案的所有者仍然是應用的所有者,但正確打開了全域性的讀寫許可權,其它應用因此可以訪問這些檔案。

使用Permission

預設情況下一個基本的Android應用不含有任何Permission定義,也就是說該應用無權執行一些可能對使用者或者裝置上資料造成不良影響的操作。為了訪問裝置的某些受限的功能,你必須在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>


    在安裝應用時,應用所需的許可權由應用安裝程式來賦予應用,這將根據應用證書籤名並由使用者來決定。而在應用執行時無需使用者再檢查許可權。要麼是在安裝時賦予應用使用某些功能對應的許可權,之後應用可以任意使用該功能,要麼是安裝時拒絕賦予了某些許可權,之後應用在使用這些功能時會失敗而不會提示使用者。

通常情況下,在許可權失敗時會導致丟擲SecurtyException異常,但系統不保證總是會這樣。比如,方法sendBroadcast(Intent)在就資料傳送到每個Receiver過程中會檢查所需許可權,在方法結束後,如果有許可權失敗,你不會接收到異常。而在幾乎所有情況下,所有的許可權失敗都會在寫到系統日誌中。

Android系統支援的所有Permission都可以在包Manifest.permission中找到。應用程式也可以自己定義和強化許可權。

在應用執行時,某個特定的安全許可權可以在下面幾種情況下強化執行:

·        執行某個系統呼叫時,以阻止應用執行某個特定的功能。

·        啟動某個Activity時,以阻止應用啟動其它應用中的Activity。

·        傳送和接受廣播訊息時,來控制誰可以傳送廣播訊息,誰可以接收廣播訊息。

·        訪問某個ContentProvider時。

·        繫結到某個Service時。

申明和執行許可權

為了能夠使用自定義的許可權,你必須使用<permission>標記在AndroidManifest.xml檔案中申明。

比如,如果一個應用需要控制哪個別的應用能夠啟動它定義的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>


    屬性<protectionLevel>是必須的,它告訴作業系統如何通知使用者應用需要哪些許可權,或者誰能夠使用這個許可權。

屬性<permssionGroup>是可選的,系統主要用它來幫助顯示許可權給使用者。你通常可以把這個屬性設定成標準系統組,在極少情況下,你可以將它設定成自定義的組。建議使用預定義的permission組,這樣可以簡化許可權使用者介面顯示。

要注意的是Label(標題)和Description(描述)這兩個屬性也是必須的。它們的值為字串或字串資源,用來顯示給使用者看。標題應當簡潔明瞭,簡要標識該許可權需要保護的功能,而描述可以描述一下具有該許可權時能夠執行的操作。Android對於描述使用的慣例是兩行,第一行描述該許可權,第二行給出警告,在擁有該許可權時有那些不好的事情可能發生。

下例為使用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>


在AndroidManifest.xml中強制執行許可權

在程式清單檔案AndroidManifest.xml中可以定義高一層次的許可權申明以限制應用中整個元件的訪問。這需要在指定的元件描述中新增Android:permission屬性來定義需要哪些許可權才能夠使用該元件。

·        Activity許可權 (應用到<activity>標記)限制誰可以啟動該Activity。這個許可權的檢查是在呼叫Context.startActivity()和Activity.startActivityForResult()時進行。如果呼叫者不擁有所需許可權系統將丟擲SecurityException異常。

·        Service 許可權 (應用到<service>標記)限制誰可以啟動或繫結該Service。該許可權的檢查是在呼叫Context.startService(),Context.stopService()和Context.bindService()時進行。如果呼叫者不擁有所需許可權系統將丟擲SecurityException異常。

·        BroadcastReceive許可權(應用到<receive>標記)限制誰可以傳送廣播資訊給指定的Receiver。該許可權的檢查發生在Context.sendBroadcast()返回以後,系統會試圖將提交的廣播資訊傳送到指定的Receiver。因此,此時許可權檢查失敗不會給呼叫者丟擲異常。系統只是不傳送該資訊。同樣,可以為Context.registerReceiver()新增許可權控制以控制誰可以傳送廣播訊息給使用程式註冊的Receiver。此外,也可以為Context.sendBroadcast()新增許可權控制以限制哪個BroadcastReceiver可以接受廣播訊息。

·        ContentProvider許可權(應用到<provider>標記)限制誰可以訪問指定ContentProvider中的資料(ContentProvider還支援額外的非常重要的安全機制—URI許可權,參見後面內容)。和其它程式元件不同的是,ContentProvider許可權可以定義兩個許可權,一是android:readPermission限制誰可以讀取指定ContentProvider中的資料,另外一個是android:writePermission限制誰可以寫資料到指定ContentProvider。要注意的是,如果某個ContentProvider同時定義了讀寫許可權,如果只擁有寫許可權並不意味著你可以讀取該ContentProvider中的資料。該許可權的檢查是在第一次獲取該ContentProvider物件時進行,如果呼叫者不擁有兩個許可權中任意一個,系統將丟擲SecurityException異常。在使用ContentProvider進行讀寫操作時,ContentResolver.insert(),ContentResolver.query()需要呼叫者擁有讀許可權,而ContentReslover.delete()和ContentResolver.update()需要呼叫者擁有寫許可權。如果呼叫者不具有所需許可權系統將丟擲SecurityException異常。

 

在傳送廣播訊息時執行許可權

除了上面說的用來限制誰可以給註冊過的BroadcastReceiver傳送訊息的許可權外,你也可以在呼叫Context.sendBroadcast()方法傳送廣播訊息時新增許可權,用來限制可以接收該種廣播訊息的BroadcastReceiver必須擁有的許可權。

要注意是,廣播訊息的傳送者和接收者都可以使用許可權。此時,兩類許可權都需要通過檢查才能完成訊息的順利傳送。

其它許可權強化機制

在使用某個Service時,可以執行進一步細化的許可權。這是通過呼叫方法Context.checkCallingPermission() 方法來完成的。通過傳入所需的許可權定義字串,該方法將返回一個整數來標明呼叫程序是否擁有指定許可權。要注意的該方法只能在呼叫其它程序中某個方法時使用,通常是通過由Service定義的IDL介面來定義的。

此外還幾種有用的方法來檢查許可權,比如你已知其它程序的識別符號(ID),你可以使用Context.checkPermission(String,int,int)方法來檢查指定程序中某個許可權的狀態。或者你有某個其它應用安裝包的名稱,你也可以直接使用PackageManager物件的Context.checkPermission(String,Sting)方法來檢查指定的安裝包是否已被賦予了所檢查的許可權。

 

URI許可權

上面介紹過的許可權機制對於使用ContentProvider時常常不能滿足要求。一個ContentProvider可以使用讀,寫許可權來保護其中的資料,而使用ContentProvider的客戶端也需要把指定的URI資源發給其它某個應用並由其來處理。一個典型的例子為郵件中的附件。訪問郵件應該使用許可權來控制,因為郵件是有關使用者隱私的資料。然而,如果一個指向影象的URI資源傳送個某個影象瀏覽應用,這個影象瀏覽應用不使用者訪問郵件的許可權(它也沒有理由需要有訪問郵件的許可權)。

解決這種問題的方法是使用URI許可權。在啟動一個Activity或者返回結果給某個Activity時,呼叫者可以設定Intent.FLAG_GRANT_READ_URI_PERMISSION或 Intent_FLAG_GRANT_WRITE_URI_PERMISSION標記。這將賦予接收URI資源的Activity相應的許可權來訪問Intent中特定的URI資料,而無需關心接收URI資源的Activity是否擁有對給定ContentPrvoider的訪問許可權。

然而賦予這種URI許可權依然需要包含這些URI資源的ContentProvider配合。強烈建議指定的ContentProvider在<grant-uri-permission>標記中通過屬性android:grantUriPermissions定義它支援的URL許可權。

 

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述