Zwiększanie bezpieczeństwa dzięki zasadom zarządzania urządzeniami

Wycofanie aplikacji do zarządzania urządzeniem Niektóre zasady administracyjne zostały oznaczone jako wycofane po wywołaniu przez administratora urządzenia. Więcej informacji i opcje migracji znajdziesz w artykule o wycofywaniu uprawnień administratora urządzenia.

Od wersji 2.2 (poziom interfejsu API 8) platforma Android oferuje funkcje zarządzania urządzeniami na poziomie systemu za pomocą interfejsów API do administrowania urządzeniem.

Z tej lekcji dowiesz się, jak stworzyć aplikację chroniącą prywatność, która zarządza dostępem do treści przez egzekwowanie zasad zarządzania urządzeniami. Aplikację można skonfigurować w taki sposób, aby przed wyświetleniem użytkownikowi treści podlegających ograniczeniom ustawiono hasło blokady ekranu o wystarczającej sile.

Zdefiniuj i zadeklaruj zasadę

Najpierw musisz określić rodzaje zasad, które mają być obsługiwane na poziomie funkcjonalnym. Zasady mogą obejmować siłę hasła blokady ekranu, czas wygaśnięcia, szyfrowanie itp.

W pliku res/xml/device_admin.xml musisz zadeklarować wybrany zestaw zasad, który będzie egzekwowany przez aplikację. Plik manifestu Androida powinien też odwoływać się do zadeklarowanego zestawu zasad.

Każda zadeklarowana zasada odpowiada pewnej liczbie powiązanych metod zasad dotyczących urządzeń w DevicePolicyManager (przykłady to określenie minimalnej długości hasła i minimalnej liczby wielkich liter). Jeśli aplikacja spróbuje wywołać metody, których odpowiednia zasada nie jest zadeklarowana w pliku XML, w czasie działania zostanie zwrócony kod SecurityException. Inne uprawnienia, np. force-lock, są dostępne, jeśli aplikacja służy do zarządzania innymi rodzajami zasad. Jak zobaczysz później, w ramach procesu aktywacji administratora urządzenia lista zadeklarowanych zasad zostanie wyświetlona użytkownikowi na ekranie systemu.

Ten fragment kodu deklaruje zasady dotyczące limitów haseł w res/xml/device_admin.xml:

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

Kod XML deklaracji zasad, do którego odwołuje się plik manifestu Androida:

<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>

Tworzenie odbiornika administrowania urządzeniem

Utwórz odbiornika transmisji administracji urządzenia, który będzie otrzymywać powiadomienia o zdarzeniach związanych z zasadami, które zostały przez Ciebie zadeklarowane obsługiwane. Aplikacja może selektywnie zastępować metody wywołania zwrotnego.

Jeśli w przykładowej aplikacji Administrator urządzenia wyłączy administratora urządzenia, skonfigurowana zasada zostanie wykasowana ze współdzielonego ustawienia. Musisz rozważyć wdrożenie logiki biznesowej, która pasuje do Twojego przypadku użycia. Aplikacja może na przykład podejmować pewne działania, aby zminimalizować ryzyko związane z bezpieczeństwem, wdrażając pewną kombinację usuwania danych wrażliwych z urządzenia, wyłączania synchronizacji zdalnej, powiadamiania administratora itp.

Aby odbiornik działał, musisz zarejestrować go w pliku manifestu Androida, jak pokazano we fragmencie powyżej.

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();
    }
}

Aktywowanie administratora urządzenia

Zanim wyegzekwujesz jakiekolwiek zasady, użytkownik musi ręcznie aktywować aplikację jako administrator urządzenia. Fragment kodu poniżej pokazuje, jak wywołać działanie ustawień, za pomocą którego użytkownik może aktywować Twoją aplikację. Warto dołączyć tekst wyjaśniający użytkownikom, dlaczego aplikacja prosi o zgodę na bycie administratorem urządzenia. W tym celu wskaż w intencji dodatkowe informacje o EXTRA_ADD_EXPLANATION.

Rysunek 1. Ekran aktywacji użytkownika, na którym możesz podać opis zasad dotyczących urządzeń.

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);
}

Jeśli użytkownik wybierze opcję „Aktywuj”, aplikacja zostanie administratorem urządzenia i będzie mogła rozpocząć konfigurowanie i egzekwowanie zasady.

Aplikacja musi też być przygotowana na reagowanie na sytuacje, gdy użytkownik porzuci proces aktywacji przez naciśnięcie przycisku Anuluj, Wstecz lub ekranu głównego. Dlatego funkcja onResume() w aktywności związanej z konfigurowaniem zasad musi mieć logikę do ponownej oceny warunku i w razie potrzeby zaprezentować użytkownikowi opcję aktywacji administratora urządzenia.

Wdrażanie kontrolera zasad dotyczących urządzeń

Po aktywowaniu administratora urządzenia aplikacja konfiguruje Menedżera zasad dotyczących urządzeń przy użyciu żądanej zasady. Pamiętaj, że z każdą wersją Androida dodajemy nowe zasady. Warto sprawdzić wersję aplikacji, jeśli używasz nowych zasad i jednocześnie obsługujesz starsze wersje platformy. Na przykład zasada Minimalna wielkość liter jest dostępna tylko w przypadku interfejsu API na poziomie 11 (Honeycomb) lub wyższym. Poniższy kod pokazuje, jak sprawdzić wersję w czasie działania.

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);
}

Na tym etapie aplikacja może egzekwować te zasady. Aplikacja nie ma dostępu do rzeczywistego hasła blokady ekranu, ale za pomocą interfejsu Device Policy Manager API może określić, czy istniejące hasło spełnia wymagane zasady. Jeśli okaże się, że istniejące hasło blokady ekranu jest niewystarczające, interfejs API zarządzania urządzeniem nie podejmie automatycznie odpowiednich działań naprawczych. Zadaniem aplikacji jest jawne uruchomienie w niej ekranu zmiany hasła systemowego. Przykład:

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);
}

Zwykle użytkownik może wybrać jeden z dostępnych mechanizmów blokowania, np. Brak, Wzór, Kod PIN (liczbowy) lub Hasło (alfanumeryczny). Po skonfigurowaniu zasad dotyczących haseł wyłączane są typy haseł, które są słabsze niż te zdefiniowane w zasadzie. Jeśli na przykład skonfigurowana jest jakość haseł „Liczba”, użytkownik może wybrać tylko kod PIN (numeryczny) lub Hasło (alfanumeryczne).

Po prawidłowym ustawieniu urządzenia przez ustawienie odpowiedniego hasła blokady ekranu aplikacja zezwala na dostęp do zabezpieczonej zawartości.

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));
}