Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 開發入門 >> 利用沙箱、應用程序簽名和權限增強應用程序安全性

利用沙箱、應用程序簽名和權限增強應用程序安全性

編輯:開發入門

概述

Android 包括一個應用程序框架、幾個應用程序庫和一個基於 Dalvik 虛擬機的運行時,所有這些都運行在 Linux® 內核之上。通過利用 Linux 內核的優勢,android 得到了大量操作系統服務,包括進程和內存管理、網絡堆棧、驅動程序、硬件抽象層以及與本文主題 —— 安全性 —— 相關的服務。

常用縮寫詞

  • ADT:android 開發工具
  • API:應用程序編程接口
  • IDE:集成開發環境
  • JDK:Java 開發包
  • URL:統一資源標識符
  • XML:可擴展標記語言

前提條件
 

要跟隨本文,需要具備以下技能和工具:

  • 基本了解 Java™ 技術和如何使用 Eclipse(或者您喜歡的 IDE)
  • Java Development Kit(需要版本 5 或 6)
  • Eclipse(版本 3.4 或 3.5)
  • android SDK 和 ADT 插件

有關下載和設置方面的信息,請參見本文結尾的 參考資料 部分。


沙箱、進程和權限

用戶 ID:Linux 與 android

在 Linux 中,一個用戶 ID 識別一個給定用戶;在 android 上,一個用戶 ID 識別一個應用程序。應用程序在安裝時被分配用戶 ID,應用程序在設備上的存續期間內,用戶 ID 保持不變。權限是關於允許或限制應用程序(而不是用戶)訪問設備資源。

Android 使用沙箱的概念來實現應用程序之間的分離和權限,以允許或拒絕一個應用程序訪問設備的資源,比如說文件和目錄、網絡、傳感器和 API。為此,android 使用一些 Linux 實用工具(比如說進程級別的安全性、與應用程序相關的用戶和組 ID,以及權限),來實現應用程序被允許執行的操作。

概念上講,沙箱可以表示為 圖 1 所示。


圖 1. 兩個 android 應用程序,各自在其自己的基本沙箱或進程上
圖:兩個 Android 應用程序,各自在其自己的基本沙箱或進程上(具有不同的用戶 ID) 
 

Android 應用程序運行在它們自己的 Linux 進程上,並被分配一個惟一的用戶 ID。默認情況下,運行在基本沙箱進程中的應用程序沒有被分配權限,因而防止了此類應用程序訪問系統或資源。但是 android 應用程序可以通過應用程序的 manifest 文件請求權限。

通過做到以下兩點,android 應用程序可以允許其他應用程序訪問它們的資源:

  • 聲明適當的 manifest 權限
  • 與其他受信任的應用程序運行在同一進程中,從而共享對其數據和代碼的訪問

後者演示在 圖 2 中。


圖 2. 兩個 android 應用程序,運行在同一進程上
圖:兩個 Android 應用程序,運行在同一進程上(具有相同的數字簽名和相同的 Linux 用戶 ID) 
 

不同的應用程序可以運行在相同的進程中。對於此方法,首先必須使用相同的私鑰簽署這些應用程序,然後必須使用 manifest 文件給它們分配相同的 Linux 用戶 ID,這通過用相同的值/名定義 manifest 屬性 android:sharedUserId 來做到。


開發人員用例

圖 3 演示了很多在開發 android 應用程序時會發現的與安全性相關的用例


圖 3. 編寫 android 應用程序時出現的安全領域
圖:編寫 Android 應用程序時出現的安全領域 
 

  • 應用程序或代碼簽名是這樣一個過程,即生成私有、公共密鑰和公共密鑰證書,簽署和優化應用程序。
  • 權限是 Android 平台的一種安全機制,以允許或限制應用程序訪問受限的 API 和資源。默認情況下,android 應用程序沒有被授予任何權限,不允許它們訪問設備上受保護的 API 或資源,從而保證了它們的安全。權限必須被請求,定義了定制的權限,文件和內容提供者就可以受到保護。確保在運行時檢查、執行、授予和撤銷權限。

接下來,更加詳細地來看一下每個安全領域。


應用程序簽名

所有 android 應用程序都必須被簽名。應用程序或代碼簽名是一個這樣的過程,即使用私有密鑰數字地簽署一個給定的應用程序,以便:

  • 識別代碼的作者
  • 檢測應用程序是否發生了改變
  • 在應用程序之間建立信任

基於這一信任關系,應用程序可以安全地共享代碼和數據。

使用相同數字簽名簽署的兩個應用程序可以相互授予權限來訪問基於簽名的 API,如果它們共享用戶 ID,那麼也可以運行在同一進程中,從而允許訪問對方的代碼和數據。

應用程序簽名首先是生成一個私有、公共密鑰對和一個相關公共密鑰證書,簡稱為公共密鑰證書。

構建 android 應用程序時可以采用調試模式發布模式

  • 使用 Android 構建工具(命令行和 Eclipse ADT)構建的應用程序是用一個調試私有密鑰自動簽名的;這些應用程序被稱為調試模式應用程序。調試模式應用程序用於測試,不能夠發布。注意,未簽名的或者使用調試私有密鑰簽名的應用程序不能夠通過 android Market 發布。
  • 您准備發布自己的應用程序時,必須構建一個發布模式的版本,這意味著用私有密鑰簽署應用程序。

Android 中的代碼簽名采用一種比其他移動平台中要簡單得多的方式。在 android 上,證書可以是自簽名的,這就是說,無需證書授權。這種方法簡化了發布過程和相關的成本。

接下來,介紹如何從命令行以及通過使用 Eclipse ADT 手動簽署 android 應用程序。本文中不介紹第三種方法,即使用 Ant。

手動創建私有、公共密鑰和公共密鑰證書

回想一下,調試模式應用程序是使用調試密鑰/證書由構建工具自動簽名的。要簽署一個發布模式的應用程序,首先必須生成私有、公共密鑰對和公共密鑰證書。可以手動地或者通過使用 Eclipse ADT 簽署應用程序。兩種方法中都使用了 Java Developer Kit (JDK) keytool 密鑰和證書管理實用工具。

要手動生成私有、公共密鑰信息,可以從命令行使用 keytool,如清單 1 所示。


清單 1. 使用 keytool 生成私有/公共密鑰和證書

				
keytool -genkey -v -alias <alias_name> -keystore <keystore.name> 
-keyalg RSA -keysize 2048 -validity <number of days>

 

注意:清單 1 假設 JDK 已安裝在您的計算機上,並且 Java_HOME路徑被正確定義為指向您的 JDK 目錄(參見 參考資料,獲得下載和設置信息)。

在 清單 1 中,-genkey 表示一個公共、私有密鑰對項,以及一個 X.509 v1 自簽署的單個元素證書鏈,其中包含生成的公共密鑰。-v表示冗長模式。-alias 是用於 keystore 項的別名,keystore 存儲生成的私有密鑰和證書。-keystore 表示使用的密鑰倉庫的名稱。-keyalg 是用來生成密鑰對的算法。-keysize 是生成的密鑰大小,其中默認大小是 1024,但是推薦大小是 2048。-validity 是有效天數;推薦采用大於 1000 的值。

注意:生成密鑰之後,一定要保證密鑰的安全。不要共享私有密鑰,也不要在命令行或腳本中指定密鑰;注意,keytool 和 jarsigner 會提示輸入密碼。關於這一技巧和其他技巧,請參考 android Developers 網站的 “Securing Your Private Key”(參見 參考資料 中的鏈接)。

Keytool 提示您輸入名和姓、公司、城市、州、國家,從這些信息生成一個 X.500 Distinguished Name(更多信息請參見 參考資料),還要輸入保護私有密鑰和密鑰倉庫本身的密碼。

對於有效期,請確保使用超出應用程序本身和相關應用程序預期生命期的時期。如果您是在 Android Market 上發布應用程序,那麼有效期必須晚於 2033 年 10 月 22 日結束;否則不能上載。此外,擁有長壽命的證書讓升級應用程序更為容易。幸運的是,android Market 強制采用長壽命的證書,以幫助您避免此類問題。

手動簽署應用程序

接下來,使用 jarsigner 工具(它是 JDK 的一部分)簽署未簽名的應用程序:

jarsigner -verbose -keystore <keystore.name> <my_application.apk> <alias_name>

 

在上述代碼中,-verbose 表示冗長模式,-keystore 表示使用的密鑰倉庫的名稱。接下來是應用程序的名稱 (.apk),最後是用於私有密鑰的別名。

Jarsigner 提示您輸入使用密鑰倉庫和私有密鑰時的密碼。

應用程序可以使用不同的密鑰進行多次簽名,用相同私有密鑰簽名的應用程序之間可以建立一種信任關系,並且可以運行在同一進程中,共享代碼和數據。

手動優化應用程序

簽署過程的最後一步是優化應用程序,以便數據邊界與文件的開始是內存對齊的,這種技術有助於改善運行時性能和內存利用率。要簽署應用程序,可以使用 zipalign

zipalign -v 4 your_project_name-unaligned.apk your_project_name.apk

 

在前面的代碼中,-v 表示冗長輸出。數字 4 表示使用四字節對齊(總是使用四字節)。下一個參數是輸入已簽署應用程序的文件名 (.apk),它必須用您的私有密鑰簽署。最後一個參數是輸出文件名;如果覆蓋現有應用程序,則添加一個 -f

手動驗證應用程序已經簽署

要驗證應用程序已經簽署,可以使用 Jarsigner,這次傳遞 -verify標志:

jarsigner -verify -verbose -certs my_application.apk

 

在前面的代碼中,-verify 表示驗證應用程序;-verbose 表示冗長模式;-certs 表示展示創建密鑰的 CN 字段,最後一個參數是要驗證的 android 應用程序包的名稱。

注意:如果 CN 讀入 "Android Debug",那麼意味著應用程序是用調試密鑰簽署的,這表明不能發布;如果您計劃在 android Market 上發布您的應用程序,一定要記得使用私有密鑰。

剛才學習了如何手動創建私有、公共密鑰,以及簽署和優化應用程序。接下來,了解如何使用 Eclipse ADT 自動創建私有、公共密鑰,以及簽署和優化應用程序。


使用 Eclipse ADT 創建密鑰和證書,以及簽署和優化應用程序

要使用 Eclipse ADT 生成密鑰,必須導出應用程序。有兩種方法從 Eclipse 導出應用程序:

  • 導出您必須手動簽署的應用程序的未簽署 版本
  • 導出應用程序的已簽署 版本,其中所有步驟都由 ADT 為您代勞

導出未簽署的應用程序

您可以導出您必須手動簽署的應用程序的未簽署版本。就是說,您需要手動運行 keytool(如前所述,是為了生成密鑰)和 Jarsigner(為了簽署應用程序),並使用 zipalign 工具優化應用程序,跟前面解釋的那樣。

要使用 ADT 導出應用程序的未簽署版本,可以右鍵單擊項目並選擇android Tools>Export Unsigned Application Package(參見 圖 4)。


圖 4. 導出未簽署的應用程序
導出未簽署的應用程序的屏幕截圖 
 

選中之後,ADT 提示您選擇將未簽署應用程序導出到的目錄。記住,一旦應用程序被導出,您就必須手動簽署和優化應用程序,跟前面介紹的那樣。

導出已簽署的應用程序

利用 Eclipse ADT,您可以導出應用程序的已簽署版本。使用這種方法,ADT 提示您輸入以下內容:

  • 使用現有 KeyStore 或者創建新的受保護 KeyStore 所需的信息
  • 創建受保護私有密鑰所需的信息
  • 生成公共密鑰證書所需的信息

要導出已簽署的應用程序,可以右鍵單擊項目,但是這一次選擇菜單項 android Tools->Export Signed Application Package,如 圖 5 所示。


圖 5. 導出已簽署的應用程序
導出已簽署的應用程序的屏幕截圖 
 

此時,Export Wizard 執行,如 圖 6 所示。


圖 6. Export Wizard
Export Wizard 的屏幕截圖 
 

在 圖 7 中,選擇一個現有的密鑰倉庫(或者創建一個新的)和證書。


圖 7. Export Wizard:密鑰倉庫選擇
Export Wizard:密鑰倉庫選擇的屏幕截圖 
 

在 圖 8 中,輸入信息以創建私有密鑰和數字證書。


圖 8. Export Wizard:創建私有密鑰和數字證書
Export Wizard:創建私有密鑰和數字證書的屏幕截圖 
 

在 圖 9 中,輸入目標文件的路徑和名稱,並驗證有效期間。


圖 9. 輸入目標文件的路徑和名稱
輸入目標文件的路徑和名稱的屏幕截圖 
 

完成時,您就有了一個發布模式的已簽署和已優化的應用程序,您可以發布它。

另外,您也可以使用 android Manifest 工具調用 Export Wizard,如 圖 10 所示。


圖 10. 使用 android Manifest 工具調用 Export Wizard
使用 Android Manifest 工具調用 Export Wizard 的屏幕截圖 
 

應用程序簽署之後,下一步由您在 manifest 中定義應用程序需要的權限。接下來將描述這一過程。

注意,Android Developer 網站有非常好的關於應用程序簽署的文檔,當有 android 平台的新版本可用時,這些文檔都會更新(參見參考資料,了解更多信息)。


使用權限

權限是一種 Android 平台安全機制,旨在允許或限制應用程序訪問受限的 API 和資源。默認情況下,android 應用程序沒有被授予權限,這通過不允許它們訪問設備上的受保護 API 或資源,確保了它們的安全。權限在安裝期間通過 manifest 文件由應用程序請求,由用戶授予或不授予。

android 定義長長的一系列 manifest 權限,以保護系統或其他應用程序的各個方面。要請求權限,可以在 manifest 文件中聲明一個<user-permission> 屬性:

<uses-permission android:name="string" />

 

其中 android:name 指定權限的名稱。

要得到所有 android 定義的 manifest 權限的列表,請參見 Manifest.permisson 頁面。清單 2 是一個 manifest 文件的例子,它請求使用 Internet 的權限和寫到外部存儲器的權限:


清單 2. 聲明(請求)權限

				
<?xml version="1.0" encoding="utf-8"?>
<manifest XMLns:android="http://schemas.android.com/apk/res/android"
      android:versionCode="1"
      android:versionName="1.0"
      package="com.cenriqueortiz.tutorials.datastore" 
      android:installLocation="auto">

    <application 
        :
        :
        :
    </application>

    <uses-permission 
        android:name="android.permission.INTERNET"/>
    <uses-permission 
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>

 

應用程序可以定義它們自己的定制權限,以保護應用程序資源。其他應用程序想要訪問一個應用程序的受保護資源,就必須通過它們自己的 manifest 文件請求適當的權限。清單 3 展示了一個如何定義權限的例子。


清單 3. 聲明定制權限

				
<permission
        XMLns:android="http://schemas.android.com/apk/res/android"
        android:name="com.cenriqueortiz.android.Access_FRIENDS_LIST"
        android:description="@string/permission_description"
        android:label="@string/permission_label"
        android:protectionLevel="normal"
    >
</permission>

 

在 清單 3 中,通過指定最少的屬性,即namedescriptionlabel 和 protectionLevel,定義了一個定制權限。也可以定義其他屬性,但是這裡沒做介紹。

特別有趣的是 android:protectionLevel 屬性,它表示系統向一個請求權限的應用程序授予(或不授予)給定的權限時應該遵循的方法。保護級別有普通 和危險。前者自動授予權限(盡管用戶在安裝之前總是可以重審),基於簽名授予權限(就是說,如果請求權限的應用程序是用同一證書簽署的);後者表示權限給予私有數據的訪問權,或者具有另一個潛在的負面影響。有關 <permission> manifest 屬性的更多信息,請參見 <permission> 頁面(參見 參考資料)。

應用程序可以限制對應用程序及其使用的系統組件(比如 Activity、Service、Content Provider 和 Broadcast Receiver)的訪問。通過像 清單 4 中那樣定義 android:permission 屬性,很容易實現這種限制。這種級別的保護讓應用程序允許或限制其他應用程序訪問系統資源。


清單 4. 定義一個活動的權限

				
<activity 
    android:name=".FriendsListActivity" 
    android:label="FrIEnds List">
    android:permission="com.cenriqueortiz.android.Access_FRIENDS_LIST"
    <intent-filter>
        :
        :
    </intent-filter>        
</activity>  

 


內容提供者和文件權限

內容提供者暴露一個公共 URI,用於惟一地識別它們的數據(參見參考資料)。要保護此內容提供者,當開始時或者從活動返回結果時,調用者可以設置 Intent.FLAG_GRANT_READ_URI_PERMISSION 和Intent.FLAG_GRANT_WRITE_URI_PERMISSION,以便授予接收活動權限,以訪問特定的數據 URI。

應用程序文件默認是受保護的。文件基於用戶 ID 受保護,因而只對所有者應用程序是可訪問的(此應用程序具有相同的用戶 ID)。正如前面介紹的,共享相同用戶 ID(並使用相同數字證書簽署)的應用程序運行在相同進程上,因而共享對它們的應用程序的訪問。

應用程序可以允許其他應用程序或進程訪問它們的文件。這種允許是通過指定適當的 MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE操作模式(以便允許對文件的讀或寫訪問)或 MODE_PRIVATE(以便以私有模式打開文件)而做到的。您可以在創建或打開文件時利用以下方法指定操作模式:

  • getSharedPreferences(filename, OperatingMode)
  • openFileOutput(filename, OperatingMode)
  • openOrCreateDatabase(filename, OperatingMode, SQLiteDatabase.CursorFactory)

運行時 Permission API

android 提供各種 API 來在運行時檢查、執行、授予和撤銷權限。這些 API 是 android.content.Context 類的一部分,這個類提供有關應用程序環境的全局信息。例如,假設您想要優雅地處理權限,您可以確定您的應用程序是否被授予了訪問 Internet 的權限(參見確定 5)。


清單 5. 使用運行時 Permission API 在運行時檢查權限

				
if (context.checkCallingOrSelfPermission(Manifest.permission.INTERNET)
        != PackageManager.PERMISSION_GRANTED) {
            // The Application requires permission to access the  
            // Internet");
} else {
    // OK to Access the Internet
}

 

要了解其他在運行時檢查、執行、授予和撤銷權限的權限 API,請參考上下文類。


結束語

本文介紹了 android 平台上的安全性,包括沙箱、應用程序簽名、應用程序權限,以及文件和內容提供者權限。閱讀完這篇介紹性文章之後,您將能夠使用 Eclipse 手動創建數字證書,請求應用程序權限,以及允許或不允許應用程序訪問文件和內容提供者。此外,您還簡要了解了權限運行時 API,這些 API 允許您在運行時檢查、執行、授予和撤銷權限。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved