透過裝置管理政策強化安全性

裝置管理員淘汰。部分管理員政策在叫用時標示為已淘汰 由裝置管理員執行如要瞭解詳情及查看遷移選項,請參閱 裝置管理員淘汰

從 Android 2.2 (API 級別 8) 開始,Android 平台提供系統層級的裝置管理服務 功能。

在這堂課中,您將學到如何建立安全感知的應用程式,以管理 內容。具體來說,您可以透過 確保在顯示密碼前,您已設定密碼強度不足的螢幕鎖定密碼。 僅限使用者存取的內容

定義並宣告政策

首先,您需要定義功能層級要支援的政策類型。政策可能會 包括螢幕鎖定密碼強度、到期逾時、加密等。

您必須宣告所選政策組合,這個應用程式將強制執行。 res/xml/device_admin.xml 檔案。Android 資訊清單也應參照 宣告的政策

每項聲明的政策都會對應至 DevicePolicyManager 中的某些相關裝置政策方法 (定義密碼長度下限和下限) 大寫字元就是兩個例子)。如果應用程式嘗試叫用 未在 XML 中宣告對應的政策,因此在執行階段會導致 SecurityException。其他權限 force-lock 等,如果應用程式希望管理 其他種類的政策接下來是裝置管理員啟用程序的一部分 使用者會在系統畫面上看到已宣告政策的清單。

下列程式碼片段在 res/xml/device_admin.xml 中宣告限制密碼政策:

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <limit-password />
    </uses-policies>
</device-admin>

Android 資訊清單中參照的政策宣告 XML:

<receiver android:name=".Policy$PolicyAdmin"
    android:permission="android.permission.BIND_DEVICE_ADMIN">
    <meta-data android:name="android.app.device_admin"
        android:resource="@xml/device_admin" />
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
</receiver>

建立裝置管理接收器

建立裝置管理廣播接收器,在您宣告支援的政策相關事件時收到通知。應用程式可選擇覆寫回呼方法。

在範例應用程式中,裝置管理員停用裝置管理員 使用者,所設定的政策會從共用偏好設定中清除。建議您考慮導入 符合用途的商業邏輯舉例來說,應用程式可能需 採取措施來降低安全性風險,方法是在 停用遠端同步處理功能、通知管理員等

為了讓廣播接收器正常運作,請務必在 Android 資訊清單中註冊該接收器,如上方程式碼片段所示。

Kotlin

class PolicyAdmin : DeviceAdminReceiver() {

    override fun onDisabled(context: Context, intent: Intent) {
        // Called when the app is about to be deactivated as a device administrator.
        // Deletes previously stored password policy.
        super.onDisabled(context, intent)
        context.getSharedPreferences(APP_PREF, Activity.MODE_PRIVATE).edit().apply {
            clear()
            apply()
        }
    }
}

Java

public static class PolicyAdmin extends DeviceAdminReceiver {

    @Override
    public void onDisabled(Context context, Intent intent) {
        // Called when the app is about to be deactivated as a device administrator.
        // Deletes previously stored password policy.
        super.onDisabled(context, intent);
        SharedPreferences prefs = context.getSharedPreferences(APP_PREF, Activity.MODE_PRIVATE);
        prefs.edit().clear().commit();
    }
}

啟用裝置管理員

強制執行任何政策之前,使用者必須以裝置手動啟用應用程式 管理員。以下程式碼片段說明如何觸發含有 使用者即可啟用您的應用程式。建議您加入說明文字來強調重點 使用者必須指定應用程式 意圖中有 EXTRA_ADD_EXPLANATION 個額外項目。

圖 1. 你可以點選這個使用者啟用畫面 請提供裝置政策說明。

Kotlin

if (!policy.isAdminActive()) {

    val activateDeviceAdminIntent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)

    activateDeviceAdminIntent.putExtra(
            DevicePolicyManager.EXTRA_DEVICE_ADMIN,
            policy.getPolicyAdmin()
    )

    // It is good practice to include the optional explanation text to
    // explain to user why the application is requesting to be a device
    // administrator. The system will display this message on the activation
    // screen.
    activateDeviceAdminIntent.putExtra(
            DevicePolicyManager.EXTRA_ADD_EXPLANATION,
            resources.getString(R.string.device_admin_activation_message)
    )

    startActivityForResult(activateDeviceAdminIntent, REQ_ACTIVATE_DEVICE_ADMIN)
}

Java

if (!policy.isAdminActive()) {

    Intent activateDeviceAdminIntent =
        new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);

    activateDeviceAdminIntent.putExtra(
        DevicePolicyManager.EXTRA_DEVICE_ADMIN,
        policy.getPolicyAdmin());

    // It is good practice to include the optional explanation text to
    // explain to user why the application is requesting to be a device
    // administrator. The system will display this message on the activation
    // screen.
    activateDeviceAdminIntent.putExtra(
        DevicePolicyManager.EXTRA_ADD_EXPLANATION,
        getResources().getString(R.string.device_admin_activation_message));

    startActivityForResult(activateDeviceAdminIntent,
        REQ_ACTIVATE_DEVICE_ADMIN);
}

如果使用者選擇「啟用」應用程式會變成裝置管理員 設定與強制執行政策

應用程式也必須做好準備,處理使用者放棄的一系列情境 按下 [取消] 按鈕、返回鍵或 [主畫面] 鍵啟用程序。因此 政策設定活動中的 onResume() 必須要有邏輯 重新評估條件,並在下列情況向使用者顯示「裝置管理員啟用」選項: 。

實作裝置政策控制器

成功啟用裝置管理員後,應用程式接著會設定裝置 政策管理工具。請注意,新的政策 每個版本的 Android。如果使用 ,同時支援舊版平台。例如「密碼下限」 大寫案件政策僅適用於 API 級別 11 (Honeycomb) 及以上級別。以下程式碼 瞭解如何在執行階段查看版本。

Kotlin

private lateinit var dpm: DevicePolicyManager
private lateinit var policyAdmin: ComponentName

dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
policyAdmin = ComponentName(context, PolicyAdmin::class.java)

dpm.apply {
    setPasswordQuality(policyAdmin, PASSWORD_QUALITY_VALUES[passwordQuality])
    setPasswordMinimumLength(policyAdmin, passwordLength)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        setPasswordMinimumUpperCase(policyAdmin, passwordMinUpperCase)
    }
}

Java

DevicePolicyManager dpm = (DevicePolicyManager)
        context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName policyAdmin = new ComponentName(context, PolicyAdmin.class);

dpm.setPasswordQuality(policyAdmin, PASSWORD_QUALITY_VALUES[passwordQuality]);
dpm.setPasswordMinimumLength(policyAdmin, passwordLength);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    dpm.setPasswordMinimumUpperCase(policyAdmin, passwordMinUpperCase);
}

此時,應用程式即可強制執行政策。應用程式無法存取 並透過 Device Policy Manager API 判斷實際的螢幕鎖定密碼 指出現有的密碼是否符合必要政策。結果判定 螢幕鎖定密碼不足,Device Management API 不會自動接收 修正方法。應用程式有責任明確啟動系統 密碼變更畫面。例如:

Kotlin

if (!dpm.isActivePasswordSufficient) {
    // Triggers password change screen in Settings.
    Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD).also { intent ->
        startActivity(intent)
    }
}

Java

if (!dpm.isActivePasswordSufficient()) {
    ...
    // Triggers password change screen in Settings.
    Intent intent =
        new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    startActivity(intent);
}

一般來說,使用者可以從可用的鎖定機制中進行選擇,例如「無」、「模式」 PIN 碼 (數字) 或密碼 (英數字元)。設定密碼政策後,系統會將這些密碼 如果類型低於政策中定義的類型,就會停用。舉例來說, 「數字」密碼品質已設定完成,使用者可選取 PIN 碼 (數字) 或密碼 (英數字元) 密碼。

設定正確的螢幕鎖定密碼,確保裝置安全後,應用程式 允許存取受保護內容

Kotlin

when {
    !dpm.isAdminActive(policyAdmin) -> {
        // Activates device administrator.
        ...
    }
    !dpm.isActivePasswordSufficient -> {
        // Launches password set-up screen in Settings.
        ...
    }
    else -> {
        // Grants access to secure content.
        ...
        startActivity(Intent(context, SecureActivity::class.java))
    }
}

Java

if (!dpm.isAdminActive(..)) {
    // Activates device administrator.
    ...
} else if (!dpm.isActivePasswordSufficient()) {
    // Launches password set-up screen in Settings.
    ...
} else {
    // Grants access to secure content.
    ...
    startActivity(new Intent(context, SecureActivity.class));
}