Подходы для создания системы управления доступом устройства на ОС Android. Что изменилось в 2023 году?

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Максим Денисов, разработчик в Лиге Цифровой Экономики, поделился опытом создания системы управления доступом на Android и рассказал, как менялся подход к контролю доступа.

В этой статье расскажу, как изменился подход к контролю доступа к корпоративному устройству внутри одной компании.

Нашей задачей была разработка приложения, которое заблокирует доступ к потерянному устройству на Android, будет отправлять действия пользователя на сервер и обновляться также с сервера.

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

Разработка началась в 2015 году, когда 5-я версия Android была последней.

1.           Подход на основе блокирующей view

1.1.  Блокировка

Суть подхода — работа блокирующего окна, которое отображается поверх всех остальных. После авторизации оно закрывается.

В манифесте приложения нужно добавить следующее разрешение:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

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

У блокирующего экрана добавить свойства:

WindowManager.LayoutParams.TYPE_SYSTEM_ALERT

WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN

Кроме того, следует создать сервис, в котором ресивер отлавливает выключение экрана и вызывает блокирующую view.

private BroadcastReceiver screenStatusReceiver = new BroadcastReceiver() {
   @Override
   public void onReceive(Context context, Intent intent) {
       if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
           startLockScreenActivity(context);
       }
   }
 
public static void startLockScreenActivity(Context context) {
   Intent activityIntent = new Intent(context, LockActivity.class);
   activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     activityIntent.addFlags(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
   context.startActivity(activityIntent);
}

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

Intent activateDeviceAdmin = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);

activateDeviceAdmin.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, policyManager.getAdminComponent());

activateDeviceAdmin.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "After activating admin, you will be able to block application uninstallation.");

startActivityForResult(activateDeviceAdmin, PolicyManager.DPM_ACTIVATION_REQUEST_CODE);

При попытке удалить права администратора происходит сброс к заводским настройкам.

devicePolicyManager.wipeData(0);

1.2.  События безопасности

Для хранения событий пользователя применялась локальная база данных.

@Entity(tableName = "events")

data class Event(

       @PrimaryKey(autoGenerate = true)

       @ColumnInfo(name = "id")

       val id: Int,

       @ColumnInfo(name = "login")

       val login: String? = null,

……

 Синхронизация происходила по таймеру.

internal inner class SyncEventTimer : TimerTask() {
   override fun run() {
       Timber.tag(TAG).d("SyncEventTimer")
       GlobalScope.launch(Dispatchers.IO) {
           try {
               sendFromLocal()
           } catch (e: Exception) {
               Timber.tag(TAG).e(e)
           }
       }
   }
}

1.3        Обновление

Обновление происходит через загрузку apk на устройство и вызов следующего интента:

           Intent intent = new Intent( Intent.ACTION_INSTALL_PACKAGE

intent.setData( apkUri );

            intent.setFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION );

           context.startActivity( intent );

Со временем появились серьезные ограничения. В 9-й и 10-й версиях Android появилась возможность убрать блокирующую view, а также не удается блокировать запуск других приложений. Когда происходило обновление, у пользователя появлялась возможность закрыть блокировщик — он «снимался» в момент обновления.

Изначально было решено устанавливать еще одно приложение, которое бы и выполняло обновление, и выдавать ему права администратора. Однако это не помогло — у пользователя по-прежнему появлялась возможность закрыть блокировщик: основной экран появлялся во время обновления, и можно было совершить какие-либо действия с устройством.

Поэтому для новых версий Android такой подход, к сожалению, не применим.

2.               Подход на основе библиотеки knox от Samsung

Дальнейшее развитие приложения потребовало контроль над запущенными приложениями. Для этой задачи использовалась библиотека Knox от Samsung. Помимо необходимой функции, библиотека упрощает работу с разрешениями и блокировкой устройства.

Для ее работы в манифесте добавляются разрешения:

<uses-permission android:name="com.samsung.android.knox.permission.KNOX_KIOSK_MODE" />
<uses-permission android:name="com.samsung.android.knox.permission.KNOX_CUSTOM_SYSTEM " />
<uses-permission android:name="com.samsung.android.knox.permission.KNOX_APP_MGMT" />
<uses-permission android:name="com.samsung.android.knox.permission.KNOX_ADVANCED_SECURITY" />
Для работы библиотеки необходимо ввести ключ лицензии.
val mSKL = KnoxEnterpriseLicenseManager.getInstance(context)
mSKL.activateLicense(“key”, context.packageName)

Выдача разрешений без запроса пользователю делалась так:

runtimePermissions.add("android.permission.WRITE_EXTERNAL_STORAGE");

Установка блокирующего приложения — следующим образом:

mKioskMode?.enableKioskMode(pkgName)

Отключение приложений на устройстве:

 EnterpriseDeviceManager edm = EnterpriseDeviceManager.getInstance(context);

 ApplicationPolicy appPolicy = edm.getApplicationPolicy();

appPolicy.setDisableApplication(“com.test.app”)

Проблема в том, что такой вариант работает только с техникой Samsung, а также нужно покупать ключ для использования библиотеки.

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

3. Подход на основе владельца устройства

3.1.  Установка режима device-owner

Для выдачи приложению администратора устройства необходимо выполнить команду через adb:

adb shell dpm set-device-owner ru.company.screenlocker/.AdminReceiver

3.2.  Выдача разрешений

В этом режиме приложению можно выдать любые необходимые разрешения:

val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
val cn = ComponentName(context, AdminReceiver::class.java)
 dpm.setPermissionGrantState(
   cn, context.packageName,
   Manifest.permission.REQUEST_INSTALL_PACKAGES,
   DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
)

3.3.  Запрет на изменение приложения

Запретить пользователю менять приложение можно следующей командой:

val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

val cn = ComponentName(context, AdminReceiver::class.java)

dpm.addUserRestriction(cn, UserManager.DISALLOW_APPS_CONTROL)

3.4.  Включить режим блокировки задач

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

activity.startLockTask()

3.5.  Установить свой рабочий стол

Получить список всех приложений с иконками:

val allApps = packageManager.queryIntentActivities(i, 0)
   for (ri in allApps) {
       val app = DesktopAppInfo()
       app.label = ri.loadLabel(packageManager)
       app.packageName = ri.activityInfo.packageName
       app.icon = ri.activityInfo.loadIcon(packageManager)
       loadList.add(app)
   }

Соответственно, на своем рабочем столе можно разместить только нужные приложения.

На мой взгляд, это самый актуальный на сегодняшний день формат — работает на всех устройствах Android и на новых версиях ОС. Однако для установки приложения администратора необходимо форматировать устройство.

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

____________________________________________

В этом материале я описал изменение подхода к контролю корпоративной техники — от устаревшего к актуальному и на сегодняшний день. Имели ли вы дело с каким-либо их них?

Источник: https://habr.com/ru/company/digitalleague/blog/722232/


Интересные статьи

Интересные статьи

Привет! Меня зовут Саша Шутай, я тимлид в AGIMA. В прошлой статье я рассказывал, что делать, если на проекте Bitrix сожительствует с Vue.js и поисковые боты не видят контента сайта. А в этой помогу ра...
Здравствуй, читатель. Хотелось бы ненадолго отвлечь твое внимание от новостей и историй данной технической статьей. Поэтому пусть такой "кликбейтный" затравочный заголовок не ...
В предыдущей статье мы научились подавать Vendor команды в устройство USB3.0 на базе контроллера FX3 и реализовали программную шину SPI. Сегодня мы продолжим начатое и сделаем компонент S...
Я давно знаком с Битрикс24, ещё дольше с 1С-Битрикс и, конечно же, неоднократно имел дела с интернет-магазинами которые работают на нём. Да, конечно это дорого, долго, местами неуклюже...
VUE.JS - это javascript фрэймворк, с версии 18.5 его добавили в ядро битрикса, поэтому можно его использовать из коробки.