Melhorar a segurança com políticas de gerenciamento de dispositivos

Suspensão de uso do administrador do dispositivo. Algumas políticas de administrador foram marcadas como descontinuadas quando invocadas por um administrador do dispositivo. Para saber mais e ver as opções de migração, consulte Descontinuação do administrador do dispositivo.

Desde o Android 2.2 (nível 8 da API), a plataforma Android oferece recursos de gerenciamento de dispositivos no nível do sistema usando as APIs Device Administration.

Nesta lição, você vai aprender a criar um aplicativo com reconhecimento de segurança que gerencia o acesso ao conteúdo ao aplicar políticas de gerenciamento de dispositivos. Especificamente, o aplicativo pode ser configurado para garantir que uma senha de bloqueio de tela de força suficiente seja configurada antes de exibir conteúdo restrito para o usuário.

Definir e declarar sua política

Primeiro, é necessário definir os tipos de política a serem suportados no nível funcional. As políticas podem abranger o nível de segurança da senha de bloqueio de tela, o tempo limite de expiração, a criptografia etc.

É necessário declarar o conjunto de políticas selecionado, que será aplicado pelo aplicativo, no arquivo res/xml/device_admin.xml. O manifesto do Android também precisa fazer referência ao conjunto de políticas declarados.

Cada política declarada corresponde a um número de métodos de política do dispositivo relacionados no DevicePolicyManager. A definição do tamanho mínimo da senha e do número mínimo de caracteres maiúsculos são dois exemplos. Se um aplicativo tentar invocar métodos cuja política correspondente não foi declarada no XML, isso resultará em uma SecurityException no momento da execução. Outras permissões, como force-lock, estão disponíveis se o aplicativo pretende gerenciar outros tipos de política. Como você verá mais tarde, como parte do processo de ativação do administrador do dispositivo, a lista de políticas declaradas será apresentada ao usuário em uma tela do sistema.

O snippet a seguir declara a política de limite de senhas em res/xml/device_admin.xml:

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

XML de declaração de política referenciado no manifesto do Android:

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

Criar um receptor de administração de dispositivo

Crie um broadcast receiver de administração de dispositivo, que recebe notificações sobre eventos relacionados às políticas que declarou ter suporte. Um aplicativo pode substituir seletivamente métodos de callback.

No app de exemplo Administrador do dispositivo, quando o administrador do dispositivo é desativado pelo usuário, a política configurada é apagada da preferência compartilhada. Considere implementar uma lógica de negócios relevante para seu caso de uso. Por exemplo, o aplicativo pode realizar algumas ações para reduzir o risco de segurança, implementando alguma combinação de exclusão de dados confidenciais no dispositivo, desativação da sincronização remota, alertando um administrador etc.

Para que o broadcast receiver funcione, ele precisa ser registrado no manifesto do Android, conforme ilustrado no snippet acima.

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

Ativar o administrador do dispositivo

Antes de aplicar qualquer política, o usuário precisa ativar manualmente o aplicativo como administrador do dispositivo. O snippet abaixo ilustra como acionar a atividade de configurações em que o usuário pode ativar o aplicativo. É uma prática recomendada incluir o texto explicativo para destacar aos usuários por que o aplicativo está solicitando ser um administrador de dispositivo, especificando o extra EXTRA_ADD_EXPLANATION na intent.

Figura 1. A tela de ativação do usuário em que é possível fornecer uma descrição das políticas do dispositivo.

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

Se o usuário selecionar "Ativar", o aplicativo se tornará um administrador de dispositivo e poderá começar a configurar e aplicar a política.

O aplicativo também precisa estar preparado para lidar com situações em que o usuário abandona o processo de ativação pressionando o botão "Cancelar", a tecla "Voltar" ou a tecla "Início". Portanto, onResume() na atividade de configuração da política precisa ter lógica para reavaliar a condição e apresentar a opção de ativação do administrador do dispositivo ao usuário, se necessário.

Implementar o controlador de política de dispositivo

Depois que o administrador do dispositivo é ativado, o app configura o Gerenciador de políticas de dispositivos com a política solicitada. Lembre-se de que novas políticas são adicionadas ao Android a cada versão. Se você estiver usando novas políticas e tiver compatibilidade com versões mais antigas da plataforma, faça verificações de versão no aplicativo. Por exemplo, a política de senha mínima em letras maiúsculas só está disponível no nível 11 da API (Honeycomb) e versões mais recentes. O código a seguir demonstra como verificar a versão no momento da execução.

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

Nesse ponto, o aplicativo pode aplicar a política. Embora o aplicativo não tenha acesso à senha de bloqueio de tela real usada, a API Device Policy Manager pode determinar se a senha atual atende à política necessária. Se a senha de bloqueio de tela atual não for suficiente, a API de administração do dispositivo não vai realizar ações corretivas automaticamente. É responsabilidade do aplicativo iniciar explicitamente a tela de mudança de senha do sistema no app Configurações. Por exemplo:

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

Normalmente, o usuário pode selecionar um dos mecanismos de bloqueio disponíveis, como Nenhum, Padrão, PIN (numérico) ou Senha (alfanumérica). Quando uma política de senha é configurada, esses tipos de senha mais fracos do que os definidos na política são desativados. Por exemplo, se a qualidade da senha "Numérica" estiver configurada, o usuário poderá selecionar apenas a senha com PIN (numérico) ou Senha (alfanumérica).

Depois que o dispositivo estiver protegido adequadamente com a configuração de uma senha de bloqueio de tela adequada, o aplicativo permitirá o acesso ao conteúdo protegido.

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