Mejora la seguridad con políticas de administración de dispositivos

Baja del administrador de dispositivos. Algunas políticas de administrador dejaron de estar disponibles cuando un administrador del dispositivo las invocó. Para obtener más información y ver las opciones de migración, consulta Baja del administrador de dispositivos.

A partir de Android 2.2 (nivel de API 8), la plataforma de Android ofrece capacidades de administración de dispositivos a nivel del sistema a través de las APIs de administración de dispositivos.

En esta lección, aprenderás a crear una aplicación optimizada para la seguridad que administre el acceso a su contenido aplicando políticas de administración de dispositivos de manera forzosa. Específicamente, la aplicación se puede configurar de modo que garantice que se configure una contraseña de bloqueo de pantalla con suficiente seguridad antes de mostrar contenido restringido al usuario.

Define y declara tu política

Primero, debes definir los tipos de políticas que admitirás a nivel funcional. Las políticas pueden abarcar la seguridad de la contraseña de bloqueo de pantalla, el tiempo de espera por vencimiento, la encriptación, etcétera.

Debes declarar el conjunto de políticas seleccionado, que la aplicación aplicará de manera forzosa, en el archivo res/xml/device_admin.xml. El manifiesto de Android también debe hacer referencia al conjunto de políticas declarado.

Cada política declarada corresponde a un número de métodos de política de dispositivo relacionados en DevicePolicyManager (dos ejemplos son la longitud mínima de la contraseña y la cantidad mínima de caracteres en mayúsculas). Si una aplicación intenta invocar métodos cuya política correspondiente no está declarada en el XML, se generará una SecurityException en el tiempo de ejecución. Otros permisos, como force-lock, están disponibles si la aplicación tiene la intención de administrar otros tipos de políticas. Como verás más adelante, como parte del proceso de activación del administrador de dispositivos, la lista de políticas declaradas se presentará al usuario en una pantalla del sistema.

En el siguiente fragmento, se declara el límite de la política de contraseñas en 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 declaración de política al que se hace referencia en el manifiesto de 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>

Crea un receptor de administración de dispositivos

Crea un receptor de emisión de administración de dispositivos, que reciba notificaciones de eventos relacionados con las políticas que hayas declarado que admiten. Una aplicación puede anular de forma selectiva métodos de devolución de llamada.

En la aplicación de ejemplo, Device Admin, cuando el usuario desactiva el administrador, la política configurada se borra de la preferencia compartida. Deberías implementar una lógica empresarial que sea relevante para tu caso de uso. Por ejemplo, la aplicación puede realizar algunas acciones para mitigar el riesgo de seguridad mediante la implementación de alguna combinación de eliminación de datos sensibles en el dispositivo, inhabilitación de la sincronización remota, alerta a un administrador, etcétera.

Para que el receptor de emisión funcione, asegúrate de registrarlo en el manifiesto de Android, como se ilustra en el fragmento anterior.

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

Activa el administrador del dispositivo

Antes de aplicar políticas, el usuario debe activar manualmente la aplicación como administrador del dispositivo. En el fragmento que aparece a continuación, se muestra cómo activar la actividad de configuración en la que el usuario puede activar tu aplicación. Se recomienda incluir un texto explicativo para destacar a los usuarios por qué la aplicación solicita ser administrador de dispositivos especificando el EXTRA_ADD_EXPLANATION adicional en el intent.

Figura 1: La pantalla de activación del usuario, en la que puedes proporcionar una descripción de las políticas de tu 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);
}

Si el usuario selecciona "Activar", la aplicación se convierte en administrador del dispositivo y puede comenzar a configurar y aplicar la política.

La aplicación también debe estar preparada para controlar situaciones de retroceso en las que el usuario abandona el proceso de activación presionando el botón Cancel, la tecla Atrás o la tecla Inicio. Por lo tanto, onResume() en la actividad de configuración de políticas debe tener lógica para volver a evaluar la condición y presentar la opción de activación del administrador de dispositivos al usuario si es necesario.

Cómo implementar el controlador de política de dispositivo

Una vez que el administrador del dispositivo se activa correctamente, la aplicación configura el Administrador de políticas de dispositivos con la política solicitada. Ten en cuenta que se agregan nuevas políticas a Android con cada versión. Es apropiado realizar controles de versión en tu aplicación si usas políticas nuevas y, al mismo tiempo, admite versiones anteriores de la plataforma. Por ejemplo, la política de Mayúsculas mínimas en mayúsculas y minúsculas solo está disponible con el nivel de API 11 (Honeycomb) y versiones posteriores. En el siguiente código, se muestra cómo puedes verificar la versión durante el tiempo de ejecución.

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

En este punto, la aplicación puede aplicar la política. Si bien la aplicación no tiene acceso a la contraseña de bloqueo de pantalla real que se usó, a través de la API de Device Policy Manager, puede determinar si la contraseña existente cumple con la política requerida. Si resulta que la contraseña de bloqueo de pantalla existente no es suficiente, la API de administración de dispositivos no tomará medidas correctivas automáticamente. La aplicación debe iniciar de manera explícita la pantalla de cambio de contraseña del sistema en la app de Configuración. Por ejemplo:

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

Por lo general, el usuario puede seleccionar uno de los mecanismos de bloqueo disponibles, como Ninguno, Patrón, PIN (numérico) o Contraseña (alfanumérica). Cuando se configura una política de contraseñas, se inhabilitan los tipos de contraseñas más débiles que los definidos en la política. Por ejemplo, si está configurada la calidad de la contraseña "Numérica", el usuario puede seleccionar solo la contraseña de PIN (numérico) o de contraseña (alfanumérica).

Una vez que el dispositivo se haya asegurado correctamente mediante la configuración de una contraseña de bloqueo de pantalla adecuada, la aplicación permitirá el acceso al contenido 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));
}