Android復習(四)權限—>定義自定義應用權限
定義自定義應用權限
本文檔介紹了應用開發者如何使用 Android 提供的安全功能來定義自己的權限。通過定義自定義權限,應用可以與其他應用共享其資源和功能。如需詳細了解權限,請參閱權限概覽。
背景
Android 是一種權限分離的操作系統,其中每個應用都以不同的系統身份(Linux 用戶 ID 和組 ID)運行。系統的各個部分也會被分隔為不同的身份。因此,Linux 可以將應用同其他應用和系統隔離開來。
應用可以定義其他應用可以請求的權限,從而將自己的功能提供給后者。它們還可以定義能夠自動提供給已使用同一證書進行簽名的任何其他應用的權限。
應用簽名
所有 APK 都必須使用私鑰由其開發者持有的證書進行簽名。此證書可標識應用創作者。證書無需由證書授權機構進行簽名;Android 應用完全可以使用自簽名證書,這種做法也十分普遍。Android 中的證書旨在區分應用創作者。這樣,系統可以授予或拒絕應用對簽名級權限的訪問權限,以及授予或拒絕應用獲取與另一應用相同的 Linux 身份的請求。
用戶 ID 和文件訪問權限
安裝時,Android 會為每個軟件包提供不同的 Linux 用戶 ID。該身份在相應軟件包在該設備上存續期間將保持不變。同一軟件包在其他設備上可能具有不同的 UID;重要的是每個軟件包在指定設備上的 UID 都不同。
由于系統會在進程級別強制執行安全措施,因此任何兩個軟件包的代碼通常都無法在同一進程中運行,因為它們需要以不同的 Linux 用戶身份運行。您可以在每個軟件包的 AndroidManifest.xml 的 清單標記中使用 sharedUserId 屬性,以便為它們分配相同的用戶 ID。這樣做以后,出于安全考慮,系統隨后會將這兩個軟件包視為具有相同用戶 ID 和文件權限的同一應用。請注意,為了確保安全性,只有具有相同簽名(以及請求了相同 sharedUserId)的兩個應用才能夠獲得相同的用戶 ID。
系統會為應用存儲的所有數據分配該應用的用戶 ID,而其他軟件包通常無法訪問這些數據。
如需詳細了解 Android 的安全模型,請參閱 Android 安全性概覽。
定義并強制執行權限
要強制執行自己的權限,您首先必須使用一個或多個 <permission> 元素在您的 AndroidManifest.xml 中聲明它們。
例如,某個應用若要控制誰可以啟動它的 Activity,則可以針對此操作聲明一個權限,如下所示:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp" >
<permission
android:name="com.example.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>
注意:系統不允許多個軟件包聲明同名權限,除非所有軟件包均使用同一證書進行簽名。如果軟件包聲明了某個權限,則系統不會允許用戶安裝其他具有相同權限名稱的軟件包,除非這些軟件包使用與第一個軟件包相同的證書進行簽名。在為自定義權限命名時,為了避免命名沖突,我們建議采用反向域名方式,例如 com.example.myapp.ENGAGE_HYPERSPACE。
protectionLevel 屬性為必需項,用于告知系統如何讓用戶知道哪些應用正在請求權限或者哪些應用可以獲得該權限,如鏈接的文檔中所述。
android:permissionGroup 屬性為可選項,僅用于幫助系統向用戶顯示權限。在大多數情況下,盡管您可以自行定義組,但您應將其設置為標準系統組(在 android.Manifest.permission_group 中列出)。最好使用現有的組,因為這可以簡化用戶看到的權限界面。
您需要為權限提供標簽和說明。這些是用戶在查看權限列表 (android:label) 或有關單個權限的詳細信息 (android:description) 時能夠看到的字符串資源。標簽應當簡短,用簡短的文字描述該權限所保護的關鍵功能。該說明應該由一些句子組成,用于描述此權限允許權限獲得者執行哪些操作。我們通常會使用包含兩個句子的說明:第一句描述該權限;第二句提醒用戶在向某個應用授予該權限后可能會出現哪類錯誤。
以下示例展示了 CALL_PHONE 權限的標簽和說明:
<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call
phone numbers without your intervention. Malicious apps may
cause unexpected calls on your phone bill. Note that this does not
allow the app to call emergency numbers.</string>
創建權限組
如上一部分中所示,您可以使用 android:permissionGroup 屬性幫助系統向用戶描述權限。在大多數情況下,不妨將此屬性設置為標準系統組(在 android.Manifest.permission_group 中列出),但您也可以使用 <permission-group> 定義自己的組。
<permission-group> 元素為一組權限(包括使用 <permission> 元素在清單中聲明的權限和在其他位置聲明的權限)定義了一個標簽。這只會影響這些權限在向用戶顯示時的分組方式。<permission-group> 元素不會指定屬于該組的權限,但它會為該組提供一個名稱。
將組名稱分配給 <permission> 元素的 permissionGroup 屬性可在該組中放置權限。
<permission-tree> 元素為代碼中定義的一組權限聲明了命名空間。
自定義權限建議
應用可以定義自己的自定義權限,還可以通過定義 <uses-permission> 元素從其他應用請求自定義權限。不過,您應該仔細評估應用是否有必要這樣做。
- 如果您正在設計一系列能夠互相公開功能的應用,請嘗試將這些應用設計為每個權限僅定義一次。如果這些應用并非全都使用同一證書進行簽名,則您必須執行該操作。即使應用均使用同一證書進行簽名,每個權限僅定義一次也是最佳做法。
- 如果該功能僅適用于與提供該功能的應用具有相同簽名的應用,則您可以使用簽名檢查功能,以避免定義自定義權限。如果您的某個應用向您的另一個應用發出請求,后者會先驗證兩者是否使用相同的證書進行簽名,只有證書相同時才會遵照該請求行事。

浙公網安備 33010602011771號