При разработке мобильных приложений на платформе «1С:Предприятие» перед разработчиком неизбежно встает задача идентификации устройства. Нам необходимо точно знать, от какого именно пользователя пришел заказ, какой менеджер выполнил синхронизацию или какое устройство пытается получить доступ к конфиденциальным данным центральной базы. Идеальным решением кажется получение жесткого аппаратного ключа (например, номера телефона, IMEI или MAC-адреса), который никогда не меняется. Однако современные реалии мобильной разработки вносят жесткие коррективы в эти планы.
В этой статье мы подробно разберем, почему классические способы идентификации по "железу" больше не работают, проанализируем поведение встроенных механизмов 1С, изучим альтернативные методы получения уникальных ID и спроектируем надежную, современную архитектуру авторизации мобильных клиентов.
---
Давайте разберем ситуацию с неизменяемыми идентификаторами, такими как IMEI, серийный номер устройства или MAC-адрес сетевой карты. На ранних этапах мобильной разработки программисты часто использовали их для привязки лицензий и авторизации. Сейчас этот подход полностью заблокирован на уровне операционных систем:
READ_PHONE_STATE теперь выдается исключительно системным утилитам сотовых операторов или предустановленному ПО. Любая попытка прочитать IMEI на современном устройстве стандартными средствами вернет пустую строку или вызовет исключение безопасности.Таким образом, мы должны навсегда отказаться от попыток привязать логику работы приложения к физическому железу напрямую.
---
Самый простой способ, встроенный непосредственно в мобильную платформу 1С — это использование свойства ИдентификаторКлиента объекта СистемнаяИнформация. Давайте посмотрим, как получить этот идентификатор программно:
СисИнфо = Новый СистемнаяИнформация;
ИдентификаторУстройства = СисИнфо.ИдентификаторКлиента;
ЗаписатьВЛог("Идентификатор устройства получен: " + ИдентификаторУстройства);
Этот способ хорош тем, что он не требует никаких дополнительных настроек, разрешений в манифесте или внешних библиотек. Однако мы должны четко понимать, как этот идентификатор ведет себя на разных операционных системах при различных сценариях использования:
identifierForVendor (IDFV). Он остается абсолютно неизменным до тех пор, пока на устройстве пользователя установлено хотя бы одно мобильное приложение от данного разработчика (определяется по Team ID в аккаунте Apple Developer). Если пользователь удалит наше приложение, но на телефоне останется другое наше приложение, IDFV не изменится. Если удалить абсолютно все приложения разработчика и установить их заново — сгенерируется новый IDFV, а старый будет безвозвратно утерян.ИдентификаторКлиента. Предыдущий идентификатор в центральной базе станет недействительным ( "осиротевшим" ).---
Интересный обходной путь заключается в использовании токена службы доставки push-уведомлений. Этот идентификатор можно получить при интеграции мобильного приложения с сервисами рассылки (Google Firebase Cloud Messaging для Android и Apple Push Notification service для iOS).
Давайте проанализируем пример кода для получения этого идентификатора:
ИдентификаторПодписчикаУведомлений = МенеджерДоставляемыхУведомлений.ПолучитьИдентификаторПодписчикаУведомлений(GoogleProjectID);
Если ИдентификаторПодписчикаУведомлений <> Неопределено Тогда
ИдентификаторУстройства = ИдентификаторПодписчикаУведомлений.ИдентификаторУстройства;
КонецЕсли;
У этого метода есть свои уникальные особенности, о которых необходимо знать заранее:
GoogleProjectID) и корректно прописать его при сборке мобильного приложения в сборщике мобильных приложений 1С.---
Для устройств под управлением Android существует относительно стабильный системный идентификатор — ANDROID_ID (или SSAID - Android Settings Secure ID).
Начиная с Android 8.0, этот идентификатор имеет уникальное поведение: он генерируется отдельно для каждого приложения. Это означает, что разные приложения на одном телефоне увидят разные значения ANDROID_ID, но для нашего конкретного приложения 1С этот ID будет оставаться стабильным даже при переустановке приложения. Он изменится только при общем сбросе настроек телефона до заводских параметров (Hard Reset).
Штатными средствами языка 1С получить этот идентификатор напрямую невозможно. Для его извлечения мы должны использовать механизм внешних компонент. Нам потребуется написать (или найти готовую) внешнюю компоненту на Java/C++, которая будет вызывать нативный метод Android:
Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
После подключения компоненты в мобильном приложении 1С мы сможем обращаться к ней как к обычному объекту и получать стабильный идентификатор устройства.
---
Если мы хотим полностью контролировать процесс идентификации, мы можем самостоятельно сгенерировать уникальный идентификатор при первом запуске приложения с помощью встроенной функции платформы 1С:
НовыйID = Новый УникальныйИдентификатор;
Главная проблема этого подхода — как сохранить этот идентификатор так, чтобы он не удалился при переустановке приложения или очистке данных. Решить эту задачу можно с помощью системных механизмов операционных систем:
android:allowBackup="true"), файлы настроек 1С (в которых мы сохранили наш UUID) автоматически отправятся в облако. При переустановке приложения система сама восстановит эти файлы из облачного бэкапа, и наш UUID вернется на место.---
Проанализировав все технические ограничения, мы должны прийти к важному выводу: пытаться жестко идентифицировать физическое устройство без ведома пользователя — это тупиковый путь развития мобильной разработки. Современные стандарты безопасности требуют от нас разделения физического устройства и логического понятия "Пользователь" (или "Клиент").
Давайте рассмотрим и разберем по шагам правильный алгоритм проектирования авторизации, который гарантирует стабильную работу при любых переустановках и сменах гаджетов:
При первом запуске мобильного приложения мы проверяем, сохранены ли в локальных настройках параметры авторизации (токен доступа и UUID). Если настроек нет, мы запускаем "Мастер регистрации".
// Процедура ПриНачалеРаботыСистемы мобильного приложения
ПараметрыАвторизации = ПолучитьЛокальныеПараметрыАвторизации(); // Чтение из констант или файлов
Если Не ПараметрыАвторизации.Авторизован Тогда
ОткрытьФорму("ОбщаяФорма.ФормаРегистрацииПользователя");
КонецЕсли;
В форме регистрации мы предлагаем пользователю ввести свой номер телефона. Это самый надежный способ идентификации конкретного человека. После ввода номера приложение отправляет запрос на наш центральный сервер 1С.
Центральный сервер генерирует случайный проверочный код (например, из 4 цифр) и отправляет его пользователю на телефон через SMS-шлюз, мессенджер Telegram или посредством звонка-сброса (Flash Call).
Пользователь вводит полученный код в мобильном приложении. Приложение отправляет на сервер код подтверждения вместе со свежесгенерированным на устройстве UUID.
Давайте посмотрим на примерную схему обработки этого процесса на центральном сервере 1С:
Процедура ПодтвердитьРегистрациюНаСервере(НомерТелефона, КодПодтверждения, ИдентификаторУстройства) Экспорт
// Проверяем код подтверждения в базе данных сервера
Если ПроверитьКод(НомерТелефона, КодПодтверждения) Тогда
// Находим существующего контрагента/физлицо по номеру телефона
СсылкаНаКлиента = Справочники.Контрагенты.НайтиПоРеквизиту("НомерТелефона", НомерТелефона);
Если СсылкаНаКлиента.Пустая() Тогда
// Создаем нового клиента, если это первая регистрация
СсылкаНаКлиента = Справочники.Контрагенты.СоздатьЭлемент();
СсылкаНаКлиента.Наименование = "Новый клиент " + НомерТелефона;
СсылкаНаКлиента.НомерТелефона = НомерТелефона;
СсылкаНаКлиента.Записать();
КонецЕсли;
// Регистрируем связку Клиент - Устройство в регистре сведений
МенеджерЗаписи = РегистрыСведений.МобильныеУстройстваКлиентов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ИдентификаторУстройства = ИдентификаторУстройства;
МенеджерЗаписи.Клиент = СсылкаНаКлиента;
МенеджерЗаписи.ДатаРегистрации = ТекущаяДата();
МенеджерЗаписи.Активно = Истина;
МенеджерЗаписи.Записать();
ОтправитьМобильномуКлиентуТокенДоступа(ИдентификаторУстройства);
Иначе
ВызватьИсключение "Неверный код подтверждения!";
КонецЕсли;
КонецПроцедуры
Используя этот комплексный подход, мы обеспечиваем максимальную стабильность обмена данными и создаем безопасное, современное мобильное решение на платформе 1С:Предприятие.