標籤:des android http io os ar 使用 for strong
自訂許可權 permission
<permission
android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
android:label="@string/permlab_install_shortcut"
android:description="@string/permdesc_install_shortcut" />
聲明的含義如下;
android:label:許可權名字,顯示給使用者的,值可是一個 string 資料,例如這裡的“自訂許可權”。
android:description:比 label 更長的對許可權的描述。值是通過 resource 檔案中擷取的,不能直接寫 string 值,例如這裡的”@string/test”。
android:name:許可權名字,如果其他 app 引用該許可權需要填寫這個名字。
android:protectionLevel:權限等級,分為 4 個層級:
○normal:低風險許可權,在安裝的時候,系統會自動授予許可權給 application。
○dangerous:高風險許可權,系統不會自動授予許可權給 app,在用到的時候,會給使用者提示。
○signature:簽名許可權,在其他 app 引用聲明的許可權的時候,需要保證兩個 app 的簽名一致。這樣系統就會自動授予許可權給第三方 app,而不提示給使用者。
○signatureOrSystem:這個許可權是引用該許可權的 app 需要有和系統同樣的簽名才能授與權限,一般不推薦使用。
聲明和強制實施許可權
要強制執行自己的許可權,首先必須使用一個或多個<permission>標籤,在AndroidManifest.xml檔案中來聲明它們。
例如,應用程式想要控制誰能夠啟動它的一個Activity,就能夠用下面的方法來為這個操作聲明一個許可權:
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.me.app.myapp">
<permissionandroid: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>屬性是可選的,並且只用於協助系統把相關許可權顯示給使用者。通常用標準的系統組來設定這個屬性,當然也可以使用自己定義的組(但這很少見)。我們推薦使用既存的分組,這樣會簡化給使用者的顯示的許可權UI。
要注意的時,許可權所支援的label和description屬性。它們是能夠顯示給使用者的字串資源,android:label屬性用於許可權列表的顯示,android:description屬性用於單一許可權的詳細介紹。label屬性值應該是簡短的,用幾個關鍵的單詞來描述被許可權保護的功能。description屬性應該是許可權的詳細描述,慣例是使用兩句話,第一句話來描述許可權的功能,第二句話用來警告使用者,如果應用程式獲得了這個許可權會帶來的不利影響。
下面是一個申請CALL_PHONE許可權的label和description屬性設定的例子:
<stringname="permlab_callPhone">directly call phone numbers</string>
<stringname="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,能夠查看系統中當前定義的許可權。Settings應用的使用方法是:Settings->Applications,選擇一個應用程式,向下滾動,可以看到這個應用程式所使用的許可權。對於開發人員,帶有“-s”選項的adb命令可以用與使用者查看格式相類似的格式來顯示許可權:
$ adb shell pm list permissions -s
AllPermissions:
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
...
在AndroidManifest.xml中的強制許可權
限制訪問系統或應用程式整個組件的進階別許可權,能夠通過應用程式的AndroidManifest.xml檔案來設定。所有這些都要求在被期望的組件上包含android:permission屬性,以及用於控制訪問的命名許可權。
Activity的許可權(應用於<activity>標籤)限制了誰能夠啟動被關聯的Activity。在Context.startActivity()方法和Activity.startActivityForResult()方法執行期間要檢查這個許可權,如果調用者沒有要求的許可權,那麼就會從調用中拋出一個SecurityException異常。
Service的許可權(應用於<service>標籤)限制了誰能夠啟動或綁定被關聯的服務。在Context.startService()方法、Context.stopService()方法和Context.bindService()方法執行期間會檢查這個許可權,如果調用者沒有要求的許可權,那麼就會從調用中拋出一個SecurityException異常。
BroadcastReceiver的許可權(應用於<receiver>標籤)限制了誰能夠發送廣播通知給關聯的接收器。在Context.sendBroadcast()方法返回後會檢查這個許可權,也就是在系統試圖把提交的廣播通知發送給設定的接收器的時候。在因沒有許可權而失敗的時候,它不會向調用者拋出一個異常,它只是不發送Intent對象。同樣,給Context.registerReceiver()方法提供的許可權,是用來控制誰能夠向程式中註冊的接收器發送廣播。另一種方式是,在調用Context.sendBroadcast()方法時,提供一個許可權,來限制那個BroadcastReceiver對象能夠接收廣播通知。
ContentProvider的許可權(應用於<provider>標籤)限制了誰能夠訪問ContentProvider對象中的資料。(內容提供有一套額外的叫做URI許可權的重要且易用的安全許可權,稍後會介紹。)跟其他組件不同,它有兩個獨立的許可權屬性:android:readPermission用於限制誰能夠從提供器中讀取資料;android:writePermission用於限制誰能夠向提供器中寫入資料。要注意的是,如果提供器受到讀寫權限的保護,只擁有寫入權限並不意味著能夠從提供器中讀取資料。在首次擷取提供器和執行提供器相關的操作時,會進行許可權的檢查(如果沒有許可權,就會拋出一個SecurityException異常)。使用ContentResolver.query()方法查詢資料時,要求具有讀許可權,使用ContentResolver.insert()方法、ContentResolver.update()方法、ContentResolver.delete()方法編輯資料時,要求具有寫入權限。在所有的情境中,如果沒有要求的許可權,這個調用就會導致一個SecurityException異常被拋出。
發送廣播時的強制許可權
除了強制誰能夠把Intent對象發送給一個BroadcastReceiver對象的許可權之外,在發送一個廣播通知時,還可以指定需求許可權。通過調用帶有許可權字串的Context.sendBroadcast()方法,可以要求接收器必須要擁有這個許可權,才能夠接受這個廣播通知。
要注意的是,接收器和廣播器都能夠要求許可權,發生這種情況時,雙方的許可權都必須檢查通過後,才可以把Intent對象發送給匹配的目標。
其他強制性許可權
在調用Service過程中,可以設定更細粒度的許可權。這種設定是通過調用Context.checkCallingPermission()方法來完成的。調用時給這個方法傳入所期望的許可權字串,它會返回一個整數,它指明了所期望的許可權是否被當前調用的進程所接受。要注意的是,這種方法只能在執行來自另一個進程調用的時候使用。通常通過IDL介面來發布服務,或者是用其他的方法提供給另一個進程。
有很多有用的檢查許可權的方法。如果有另一個進程的PID,那麼就可以使用Context.checkPermission(String, int, int)方法,針對這個PID來檢查許可權。如果有另一個應用程式的包名,就可以直接使用包管理器的PackageManager.checkPermission(String, String)方法來找出這個包是否已經被授予了指定的許可權。
URI許可權
到目前為止我們所介紹的標準的許可權系統不能滿足內容提供器的使用需要。內容提供器可能要保護它自己的讀寫權限,但是為了某些操作,它的用戶端也需要把指定的URI交給另一個應用程式來處理。一個典型的樣本是Mail應用程式中的附件。郵件的訪問應該是受到許可權的保護,因為這個使用者敏感的資料。但是,如果要把一個圖片附件的URI提供給一個Image瀏覽器,那麼這個Image瀏覽器就會因沒有許可權而不能開啟這個圖片附件。
這個問題的解決方案是給每個URI都分配一個許可權,當啟動一個Activity或給一個Activity返回結果時,調用者能夠設定Intent.FLAG_GRANT_READ_URI_PERMISSION和(或)Intent.FLAG_GRANT_WRITE_URI_PERMISSION許可權。這樣就給接受Intent對象的Activity授予了訪問Intent對象中指定的資料URI的許可權,而不管它是否有權訪問與這個Intent對象對應的內容提供器中的資料許可權。
這種機制允許使用一種共同的能力樣式模型,這種模型利用使用者互動(開啟一個附件、選擇一個通訊錄等)來驅動設定更細粒度的許可權。這種機制可以有效減少應用程式所需要的許可權,只需要那些與它們直接相關行為許可權。
這種把許可權細化到URI的做法,需要持有這些URI的內容提供器的配合。強烈推薦內容提供器實現這種機制,並且通過android:grantUriPermissions屬性或<grant-uri-permissiongs>標籤來聲明它們所提供的許可權。
更多的資訊能夠在Context.grantUriPermission()、Context.revokeUriPermission()和Context.checkUriPermission()方法中找到。
Android 安全性和許可權