Безопасность

Функции в этом руководстве описывают возможности управления безопасностью, которые вы можете реализовать в приложении контроллера политики устройств (DPC). Этот документ содержит примеры кода, и вы также можете использовать приложение Test DPC в качестве источника примера кода для корпоративных функций Android.

Приложение DPC может работать в режиме владельца профиля на персональных устройствах или в режиме владельца устройства на полностью управляемых устройствах. В этой таблице указано, какие функции доступны, когда ЦОД работает в режиме владельца профиля или в режиме владельца устройства :

Особенность Владелец профиля Владелец устройства
Запретить доступ к приложениям
Блокировать приложения из неизвестных источников
Ограничить аккаунты в Google Play
Включить защиту от сброса настроек предприятия
Отслеживайте журналы корпоративных процессов и удаленные отчеты об ошибках.
Предоставить доступ и удалить доступ к сертификату клиента
Безопасный сброс пароля
Проблема безопасности рабочего профиля

Запретить доступ к приложениям

Для организаций, которые хотят запретить сотрудникам играть в игры или смотреть YouTube на своих устройствах под управлением Android в определенное время дня или в определенные дни недели, ЦОД может временно отключить доступ к приложениям.

Чтобы отключить доступ к приложениям, ЦОД, работающий в режиме владельца устройства или владельца профиля, настраивает setPackagesSuspended() , а затем выбранное приложение действует так, как если бы оно было отключено (панель запуска Google выделяет приложение серым цветом). Когда пользователь касается приложения, он видит системное диалоговое окно с сообщением о том, что приложение приостановлено.

Пока приложение приостановлено, оно не может запускать действия, а уведомления пакета подавляются. Приостановленные пакеты не отображаются на обзорном экране , они не могут отображать диалоговые окна (включая тосты и закусочные), а также не могут воспроизводить звук или вибрировать на устройстве.

Программы запуска могут узнать, приостановлено ли приложение, вызвав метод isPackageSuspended() . Подробные сведения о настройке приостановки приложения см. в setPackagesSuspended .

Блокировать приложения из неизвестных источников

Приложения, которые не установлены из Google Play (или других надежных магазинов приложений), называются приложениями из неизвестных источников . Устройства и данные могут подвергаться повышенному риску, когда люди устанавливают эти приложения.

Чтобы предотвратить установку приложений из неизвестных источников, компоненты администрирования полностью управляемых устройств и рабочих профилей могут добавить пользовательское ограничение DISALLOW_INSTALL_UNKNOWN_SOURCES .

Ограничение рабочего профиля на уровне устройства

Когда администратор рабочего профиля добавляет DISALLOW_INSTALL_UNKNOWN_SOURCES , ограничение применяется только к рабочему профилю. Однако администратор рабочего профиля может установить ограничение на уровне устройства, установив управляемую конфигурацию для Google Play. Ограничение на уровне устройства доступно в Android 8.0 (или более поздней версии), если установленное приложение Google Play имеет версию 80812500 или более позднюю.

Чтобы ограничить установку приложений только Google Play, выполните следующие действия:

  1. Установите пакет управляемой конфигурации для пакета Google Play com.android.vending .
  2. В пакете поместите логическое значение для verify_apps:device_wide_unknown_source_block .
  3. Добавьте пользовательское ограничение ENSURE_VERIFY_APPS .

В следующем примере показано, как проверить, поддерживает ли Google Play этот параметр, и установить для него значение true :

Котлин

internal val DEVICE_WIDE_UNKNOWN_SOURCES = "verify_apps:device_wide_unknown_source_block"
internal val GOOGLE_PLAY_APK = "com.android.vending"

// ...

// Add the setting to Google Play's existing managed config. Supported in
// Google Play version 80812500 or higher--older versions ignore unsupported
// settings.
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
var existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DEVICE_WIDE_UNKNOWN_SOURCES, true)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

// Make sure that Google Play Protect verifies apps.
dpm.addUserRestriction(adminName, UserManager.ENSURE_VERIFY_APPS)
dpm.addUserRestriction(adminName, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)

Ява

static final String DEVICE_WIDE_UNKNOWN_SOURCES =
    "verify_apps:device_wide_unknown_source_block";
static final String GOOGLE_PLAY_APK = "com.android.vending";

// ...


// Add the setting to Google Play's existing managed config. Supported in
// Google Play version 80812500 or higher--older versions ignore unsupported
// settings.
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
Bundle existingConfig =
    dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DEVICE_WIDE_UNKNOWN_SOURCES, true);
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

// Make sure that Google Play Protect verifies apps.
dpm.addUserRestriction(adminName, UserManager.ENSURE_VERIFY_APPS);
dpm.addUserRestriction(adminName, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);

Пользовательский интерфейс в настройках системы остается активным, но система блокирует установку приложения. Это ограничение влияет на будущие установки — ранее установленные приложения остаются на устройстве. Пользователи устройств могут продолжать устанавливать приложения в личный профиль с помощью Android Debug Bridge (adb) .

Чтобы узнать больше о неизвестных источниках, прочтите Альтернативные варианты распространения .

Ограничить аккаунты в Google Play

Иногда организация может захотеть разрешить людям добавлять личные учетные записи Google (например, для чтения почты в Gmail), но не хочет, чтобы личная учетная запись устанавливала приложения. Ваш ЦОД может установить список учетных записей, которые люди могут использовать в Google Play.

Компоненты администрирования полностью управляемых устройств или рабочих профилей могут ограничивать учетные записи, устанавливая управляемую конфигурацию для Google Play. Ограничение учетной записи доступно, если установленное приложение Google Play имеет версию 80970100 или выше.

Чтобы ограничить аккаунты в Google Play, сделайте следующее:

  1. Установите пакет управляемой конфигурации для пакета Google Play com.android.vending .
  2. В пакете поместите адреса электронной почты, разделенные запятыми, в качестве строкового значения для ключа allowed_accounts .

В следующем примере показано, как можно ограничить учетные записи:

Котлин

internal val ALLOWED_ACCOUNTS = "allowed_accounts"
internal val GOOGLE_PLAY_APK = "com.android.vending"

// ...

// Limit Google Play to one work and one personal account. Use
// a comma-separated list of account email addresses (usernames).
val googleAccounts = "ali@gmail.com,ali.connors@example.com"

// Supported in Google Play version 80970100 or higher.
val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putString(ALLOWED_ACCOUNTS, googleAccounts)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

Ява

static final String ALLOWED_ACCOUNTS = "allowed_accounts";
static final String GOOGLE_PLAY_APK = "com.android.vending";

// ...


// Limit Google Play to one work and one personal account. Use
// a comma-separated list of account email addresses (usernames).
String googleAccounts = "ali@gmail.com,ali.connors@example.com";

// Supported in Google Play version 80970100 or higher.
Bundle existingConfig =
    dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putString(ALLOWED_ACCOUNTS, googleAccounts);
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

Чтобы ограничить Google Play только рабочей учетной записью, установите для allowed_accounts одну управляемую учетную запись, как только ваш ЦОД узнает адрес электронной почты этой учетной записи. Пустая строка запрещает людям использовать любую учетную запись в Google Play.

Включить защиту от сброса настроек предприятия

Используя корпоративную защиту от сброса настроек, организации могут указать, какие учетные записи Google могут предоставить устройство, на котором были выполнены сбросы настроек.

Защита потребителя от сброса настроек к заводским настройкам предназначена для предотвращения кражи устройства. Прежде чем разрешить кому-либо инициализировать устройство после несанкционированного сброса настроек к заводским настройкам (например, с помощью EMM), мастер настройки требует, чтобы пользователь прошел аутентификацию с использованием любых учетных записей Google, которые ранее были в личном профиле устройства.

В корпоративной среде сброс настроек к заводским настройкам является важным инструментом управления устройствами сотрудников, когда сотрудник покидает организацию. Однако если организация не знает учетные данные сотрудника, защита от сброса настроек может заблокировать возможность организации выдать устройство другому сотруднику.

Обеспечение управления после сброса настроек

При работе в режиме владельца устройства ваш ЦОД может использовать setFactoryResetProtectionPolicy() чтобы контролировать, какие учетные записи имеют право на подготовку устройства после сброса настроек к заводским. Если для этой конфигурации установлено null или установлен пустой список, учетные записи, которым разрешено инициализировать устройство после сброса настроек, являются учетными записями в личном профиле устройства.

ЦОД может настраивать эти учетные записи на протяжении всего срока службы полностью управляемого устройства.

  1. ИТ-администратор может использовать метод people.get из API People со специальным значением me . Это возвращает userId для вошедшей в систему учетной записи. userID возвращается в ключе resourceName в форме people/[userId] в виде целочисленной строки. Вновь созданные учетные записи могут быть недоступны для сброса настроек в течение 72 часов.
  2. Вы также можете разрешить одному или нескольким ИТ-администраторам разблокировать устройство после сброса настроек. Попросите каждого из этих ИТ-администраторов войти в свою учетную запись Google, а также выполнить шаг 1 и поделиться с вами своим userId , чтобы вы могли добавить эти userIds в список на следующем шаге.
  3. Центр обработки данных устанавливает соответствующее ограничение приложения с помощью setFactoryResetProtectionPolicy() чтобы задать список userId , которые могут предоставить устройство для сброса настроек до заводских настроек.
  4. DPC включает учетные записи, которые могут инициализировать устройства после сброса настроек, отправляя широковещательную рассылку com.google.android.gms.auth.FRP_CONFIG_CHANGED в качестве явного намерения предотвратить удаление из-за фоновых ограничений.

Котлин

const val ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

// List of userId that can provision a factory reset device.
// You can use the value returned calling people/me endpoint.
val accountIds = listOf("000000000000000000000")

dpm.setFactoryResetProtectionPolicy(
    adminName,
    FactoryResetProtectionPolicy.Builder()
        .setFactoryResetProtectionAccounts(accountIds)
        .setFactoryResetProtectionEnabled(true)
        .build()
)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Ява

static final String ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

// List of userId that can provision a factory reset device.
// You can use the value returned calling people/me endpoint.
List<String> accountIds = new ArrayList<String>();
accountIds.add("000000000000000000000");

dpm.setFactoryResetProtectionPolicy(
    adminName,
    new FactoryResetProtectionPolicy.Builder()
        .setFactoryResetProtectionAccounts(accountIds)
        .setFactoryResetProtectionEnabled(true)
        .build());

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Наследие

Для устройств, которые не могут использовать setFactoryResetProtectionPolicy() , представленный с уровнем API 30, ваш ЦОД может использовать setApplicationRestrictions для добавления выбранных учетных записей в управляемую конфигурацию factoryResetProtectionAdmin для пакета com.google.android.gms .

Котлин

const val GOOGLE_PLAY_APK = "com.android.vending"
const val FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin"
const val DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, false)
newConfig.putString(FACTORY_RESET_PROTECTION_ADMIN, googleAccounts)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Ява

static final String GOOGLE_PLAY_APK = "com.android.vending";
static final String FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin";
static final String DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

Bundle existingConfig =
        dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, false);
newConfig.putStringArray(FACTORY_RESET_PROTECTION_ADMIN,
        accountIds.toArray(new String[accountIds.size()]));
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Отключить защиту от сброса настроек предприятия

Чтобы отключить защиту от сброса к заводским настройкам, ваш ЦОД может использовать setFactoryResetProtectionPolicy() передавая значение null .

Котлин

const val ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

dpm.setFactoryResetProtectionPolicy(adminName, null)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Ява

static final String ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

dpm.setFactoryResetProtectionPolicy(adminName, null);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Наследие

Для устройств, которые не могут использовать setFactoryResetProtectionPolicy() , представленный в уровне API 30, ваш центр обработки данных может использовать setApplicationRestrictions для установки значения ключа true в управляемой конфигурации disableFactoryResetProtectionAdmin для пакета com.google.android.gms .

Котлин

const val GOOGLE_PLAY_APK = "com.android.vending"
const val FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin"
const val DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, true)

dpm.setApplicationRestrictions(
    adminName, GOOGLE_PLAY_SERVICES_PACKAGE, restrictions
)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Ява

static final String GOOGLE_PLAY_APK = "com.android.vending";
static final String FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin";
static final String DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

Bundle existingConfig =
        dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, true);

dpm.setApplicationRestrictions(
    adminName, GOOGLE_PLAY_SERVICES_PACKAGE, restrictions);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Отслеживайте журналы корпоративных процессов и удаленные отчеты об ошибках.

В вашей консоли EMM администратор может отслеживать полностью управляемые устройства, используя журналы корпоративных процессов и удаленные отчеты об ошибках.

Журнал активности корпоративных устройств

ЦОД, работающий в режиме владельца устройства, может выявлять подозрительную активность, удаленно отслеживая активность устройства, включая запуск приложений, активность Android Debug Bridge (adb) и разблокировку экрана. Журналы процессов не требуют согласия пользователя.

Чтобы включить или отключить ведение журнала, DPC вызывает setSecurityLoggingEnabled() .

Когда доступен новый пакет журналов, DeviceAdminReceiver получает обратный вызов onSecurityLogsAvailable() . Чтобы получить журналы (после получения обратного вызова), ЦОД вызывает retrieveSecurityLogs() .

Центры обработки данных также могут вызывать retrievePreRebootSecurityLogs() для получения журналов безопасности, созданных в предыдущем цикле перезагрузки. Это интервал между последней перезагрузкой устройства и предыдущей перезагрузкой. Устройства, которые не поддерживают retrieveSecurityLogs() возвращают null . Если ваше приложение извлекает журналы с помощью методов retrievePreRebootSecurityLogs() и retrieveSecurityLogs() , вам необходимо проверить наличие повторяющихся записей.
Примечание. Эта функция регистрирует активность только на полностью управляемых устройствах с одним пользователем или аффилированными пользователями на устройстве. Эта функция не работает на персональных устройствах, поскольку она регистрирует активность на всем устройстве.

Этот параметр может быть полезен при аудите после событий безопасности, поскольку он регистрирует следующие типы действий:

  • Каждый раз приложение запускается заново. Это может помочь определить наличие вредоносного ПО, которое запускается со скомпрометированным приложением.
  • Неудачные попытки разблокировки устройства. Это может определить, произошло ли несколько неудачных попыток разблокировки за короткий период времени.
  • Потенциально опасные команды adb, когда пользователь подключает устройство к компьютеру с помощью USB-кабеля.

Подробную информацию о том, как читать журналы, см. SecurityLog .

Пока вы разрабатываете и тестируете, вы можете заставить систему сделать любые существующие журналы безопасности доступными для вашего ЦОД — вам не нужно ждать полной партии. В Android 9.0 (уровень API 28) или выше выполните в терминале следующую команду Android Debug Bridge (adb):

adb shell dpm force-security-logs

Система ограничивает частоту использования этого инструмента и сообщает о любом преднамеренном замедлении вывода терминала. Если доступны журналы, ваш ЦОД получает обратный вызов onSecurityLogsAvailable() .

Удаленно запросить отчет об ошибке

ЦОД, работающий в режиме владельца устройства, может удаленно запрашивать отчеты об ошибках для пользовательских устройств только с одним пользователем или аффилированными пользователями . Отчет об ошибке фиксирует активность устройства в тот момент, когда запрашивается отчет об ошибке, но может также включать активность за предыдущие несколько часов, в зависимости от того, как часто обновляется буфер logcat.

Чтобы удаленно запросить отчеты об ошибках, ЦОД вызывает requestBugreport() :

Предоставить доступ и удалить доступ к сертификату клиента

Если ЦОД, работающий в режиме владельца профиля или владельца устройства, предоставляет стороннему приложению возможность управлять сертификатами, приложение может предоставить себе доступ к сертификатам, которые оно устанавливает, без вмешательства пользователя. Чтобы установить сертификат, к которому смогут получить доступ все приложения в профиле, используйте installKeyPair() .

Какие параметры настраивать, смотрите installKeyPair() . Эта функция работает совместно с существующим API для управления сертификатами.

Сценарий развертывания

Без метода installKeyPair() :

  • Пользователям необходимо коснуться имени сертификата и нажать «Разрешить» каждый раз, когда они хотят предоставить доступ к сертификату.
  • Пользователи видят подсказку при установке сертификата и должны указать имя сертификата.

С помощью метода installKeyPair() :

  • Пользователям не нужно нажимать « Разрешить» каждый раз, когда они хотят предоставить доступ к сертификату.
  • Пользователи не могут переименовывать сертификаты.
  • Администраторы имеют больше контроля: они могут блокировать сертификаты для приложений, которым не нужен доступ к определенным сертификатам.

Удаление сертификата клиента

После предоставления доступа к сертификату клиента, чтобы удаленно удалить сертификаты клиента, установленные с помощью installKeyPair() , вызовите removeKeyPair() .

ЦОД, работающий в режиме владельца устройства или в режиме владельца профиля, или установщик делегированного сертификата может вызвать removeKeyPair() . При этом будет удалена пара сертификата и закрытого ключа, установленная под заданным псевдонимом закрытого ключа.

Сценарий развертывания

Используйте эту функцию, если организация переходит на более безопасную форму клиентского сертификата. Если администратор развертывает новый сертификат и его распространение занимает значительное время, он может отозвать устаревшие сертификаты после завершения миграции.

Безопасный сброс пароля

Ваш ЦОД может сбросить пароль пользователя, авторизовав изменение с помощью предварительно зарегистрированного безопасного токена. Владельцы устройств и владельцы профилей могут вызывать API безопасного сброса пароля, чтобы изменить пароль устройств и рабочих профилей соответственно. Безопасный сброс пароля заменяет resetPassword() со следующими улучшениями:

Вам следует использовать безопасный сброс пароля, если ваша сборка DPC ориентирована на Android 8.0 (уровень API 26) или выше. Вызов resetPassword() вызывает исключение SecurityException в ЦОД, ориентированных на Android 8.0 или выше, поэтому вам может потребоваться обновить ЦОД.

Установить и активировать токен

Вашему ЦОД необходимо установить и активировать токен перед сбросом пароля. Поскольку ваш ЦОД может быть не в состоянии сразу использовать токен, вы устанавливаете токен до того момента, когда ИТ-администратору может понадобиться его использовать.

Токен сброса пароля представляет собой криптостойкую случайную величину и должен иметь длину не менее 32 байтов. Создайте токен для каждого устройства и профиля — не используйте повторно и не передавайте сгенерированные токены.

Мы рекомендуем хранить токены или средства расшифровки зашифрованного токена на сервере. Если вы храните токены локально в зашифрованном хранилище учетных данных, ваш ЦОД не сможет сбросить пароль, пока пользователь не разблокирует устройство или профиль. Если вы храните токены локально в зашифрованном хранилище устройства, которое оказывается скомпрометировано, злоумышленник может использовать токен для получения доступа к рабочему профилю или основному пользователю.

Вы можете создать новый токен в своем ЦОД или получить токен с сервера. В приведенном ниже примере показано, как ЦОД сам генерирует токен и передает его на сервер:

Котлин

val token = ByteArray(32)

// Generate a new token
val random = SecureRandom()
random.nextBytes(token)

// Set the token to use at a later date
val success: Boolean
success = dpm.setResetPasswordToken(DeviceAdminReceiver.getComponentName(context), token)

// Activate the token and update success variable...

// Store the token on a server
if (success) {
 sendTokenToServer(token)
}

Ява

byte token[] = new byte[32]; // Minimum size token accepted

// Generate a new token
SecureRandom random = new SecureRandom();
random.nextBytes(token);

// Set the token to use at a later date
boolean success;
success = dpm.setResetPasswordToken(DeviceAdminReceiver.getComponentName(getContext()), token);

// Activate the token and update success variable ...

// Store the token on a server
if (success) {
 sendTokenToServer(token);
}

В большинстве случаев вашему ЦОД необходимо активировать токен после его установки. Но если у пользователя нет пароля экрана блокировки, система сразу активирует токен. Чтобы активировать токен, попросите пользователя подтвердить свои учетные данные. Ваш ЦОД может вызвать метод KeyguardManager createConfirmDeviceCredentialIntent() чтобы получить Intent , запускающее подтверждение. Объясните пользователю устройства в пользовательском интерфейсе, почему вы запрашиваете у него аутентификацию. В приведенном ниже фрагменте показано, как вы можете активировать токен в своем ЦОД:

Котлин

// In your DPC, you'll need to localize the user prompt
val ACTIVATE_TOKEN_PROMPT = "Use your credentials to enable remote password reset"
val ACTIVATE_TOKEN_REQUEST = 1

// Create or fetch a token and set it in setResetPasswordToken() ...
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, ACTIVATE_TOKEN_PROMPT)

if (confirmIntent != null) {
 startActivityForResult(confirmIntent, ACTIVATE_TOKEN_REQUEST)
 // Check your onActivityResult() callback for RESULT_OK
} else {
 // Null means the user doesn't have a lock screen so the token is already active.
 // Call isResetPasswordTokenActive() if you need to confirm
}

Ява

// In your DPC, you'll need to localize the user prompt
static final String ACTIVATE_TOKEN_PROMPT =
 "Use your credentials to enable remote password reset";
static final int ACTIVATE_TOKEN_REQUEST = 1;

// Create or fetch a token and set it in setResetPasswordToken() ...

KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
Intent confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(
  null, ACTIVATE_TOKEN_PROMPT);

if (confirmIntent != null) {
 startActivityForResult(confirmIntent, ACTIVATE_TOKEN_REQUEST);
 // Check your onActivityResult() callback for RESULT_OK
} else {
 // Null means the user doesn't have a lock screen so the token is already active.
 // Call isResetPasswordTokenActive() if you need to confirm
}

Вам необходимо активировать токен, установленный вашим ЦОД, до перезагрузки устройства. Android сохраняет неактивированный токен в памяти и не сохраняет его после перезагрузки. Если пользователь перезагружает устройство перед активацией токена, ваш ЦОД может снова установить тот же токен или сгенерировать новый токен.

Ваш ЦОД может подтвердить, что токен активен, вызвав метод isResetPasswordTokenActive() и проверив, что результат равен true .

После того, как ваш центр обработки данных установил и активировал токен, он действителен до тех пор, пока ваш центр обработки данных не удалит или не заменит токен (или пока устройство не будет сброшено до заводских настроек). Токен не зависит от пароля, и на него не влияет изменение или очистка пароля пользователем.

Удалить токен

Вы можете вызвать clearResetPasswordToken() чтобы удалить токен, установленный ранее вашим DPC. Возможно, вам придется отозвать скомпрометированный токен или удалить возможность сброса пароля. В приведенном ниже примере показано, как это можно сделать в ЦОД:

Котлин

val dpm = getDpm()
val admin = DeviceAdminReceiver.getComponentName(requireActivity())

// Clear the token
if (!dpm.clearResetPasswordToken(admin)) {
 // Report the failure and possibly try later ...
}

Ява

DevicePolicyManager dpm = getDpm();
ComponentName admin = DeviceAdminReceiver.getComponentName(getActivity());

// Clear the token
if (!dpm.clearResetPasswordToken(admin)) {
 // Report the failure and possibly try later ...
}

Сбросить пароль

Когда ИТ-администратору необходимо сбросить пароль, вызовите функцию resetPasswordWithToken() и передайте токен, который ваш ЦОД установил и активировал заранее:

Котлин

val token: ByteArray = getTokenFromServer()
val newPassword = "password"

try {
 val result: Boolean = dpm.resetPasswordWithToken(
 DeviceAdminReceiver.getComponentName(requireContext()),
 newPassword,
 token,
 0
 )

 if (result) {
 // The password is now 'password'
 } else {
 // Using 'password' doesn't meet password restrictions
 }
} catch (e: IllegalStateException) {
 // The token doesn't match the one set earlier.
}

Ява

byte token[] = getTokenFromServer();
String newPassword = "password";

try {
 boolean result = dpm.resetPasswordWithToken(
  DeviceAdminReceiver.getComponentName(getContext()), newPassword, token, 0);

 if (result) {
 // The password is now 'password'
 } else {
 // Using `password` doesn't meet password restrictions
 }
} catch (IllegalStateException e) {
 // The token doesn't match the one set earlier.
}

Вызов resetPasswordWithToken() возвращает false , и пароль не меняется, если новый пароль не соответствует следующим ограничениям:

  • Количество символов соответствует любому ограничению минимальной длины пароля. Вызовите getPasswordMinimumLength() , чтобы узнать, установил ли ИТ-администратор ограничение длины.
  • Диапазон и сложность символов в пароле соответствуют ограничениям по составу. Вызовите getPasswordQuality() , чтобы узнать, установил ли ИТ-администратор ограничение композиции.

Если ограничения качества пароля не требуют установки пароля, вы можете передать null или пустую строку в функцию resetPasswordWithToken() чтобы удалить пароль.

Проблема безопасности рабочего профиля

ЦОД, работающий в режиме владельца профиля, может потребовать от пользователей указать задачу безопасности для приложений, работающих в рабочем профиле. Система показывает угрозу безопасности, когда пользователь пытается открыть любое рабочее приложение. Если пользователь успешно выполняет проверку безопасности, система разблокирует рабочий профиль и при необходимости расшифровывает его.

Как работает проверка безопасности рабочего профиля

  1. Если ЦОД отправляет намерение ACTION_SET_NEW_PASSWORD , система предлагает пользователю настроить запрос безопасности.
  2. Центр обработки данных также может отправить намерение ACTION_SET_NEW_PARENT_PROFILE_PASSWORD , чтобы предложить пользователю установить блокировку устройства.

ЦОД может установить политику паролей для рабочих задач иначе, чем политику для паролей других устройств. Например, минимальная длина ответа на запрос устройства может отличаться от длины, необходимой для других паролей. ЦОД устанавливает политики запроса, используя обычные методы DevicePolicyManager , такие как setPasswordQuality() и setPasswordMinimumLength() .

Соображения

  • ЦОД может сбросить пароль рабочего профиля, но не может сбросить (личный) пароль устройства. Если пользователь решает установить одинаковые рабочий и личный пароли, то resetPassword() в рабочем профиле приводит к сбросу пароля только в рабочем профиле, и пароль не будет таким же, как пароль для блокировки устройства. экран.
  • ЦОД может настроить экран учетных данных для рабочей задачи, используя setOrganizationColor() и setOrganizationName() .
  • Администраторы устройств не могут использовать resetPassword() для очистки или изменения уже установленных паролей. Администраторы устройства по-прежнему могут устанавливать пароль, но только если на устройстве нет пароля, PIN-кода или шаблона.

Дополнительную информацию см. getParentProfileInstance() и справочную документацию в разделе DevicePolicyManager .