Как надежно идентифицировать мобильное устройство в 1С:Предприятии?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке мобильных приложений на платформе «1С:Предприятие» перед разработчиком неизбежно встает задача идентификации устройства. Нам необходимо точно знать, от какого именно пользователя пришел заказ, какой менеджер выполнил синхронизацию или какое устройство пытается получить доступ к конфиденциальным данным центральной базы. Идеальным решением кажется получение жесткого аппаратного ключа (например, номера телефона, IMEI или MAC-адреса), который никогда не меняется. Однако современные реалии мобильной разработки вносят жесткие коррективы в эти планы.

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

---

Почему жесткие аппаратные идентификаторы больше не работают?

Давайте разберем ситуацию с неизменяемыми идентификаторами, такими как IMEI, серийный номер устройства или MAC-адрес сетевой карты. На ранних этапах мобильной разработки программисты часто использовали их для привязки лицензий и авторизации. Сейчас этот подход полностью заблокирован на уровне операционных систем:

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

---

Вариант 1. Использование СистемнаяИнформация.ИдентификаторКлиента

Самый простой способ, встроенный непосредственно в мобильную платформу 1С — это использование свойства ИдентификаторКлиента объекта СистемнаяИнформация. Давайте посмотрим, как получить этот идентификатор программно:


СисИнфо = Новый СистемнаяИнформация;
ИдентификаторУстройства = СисИнфо.ИдентификаторКлиента;
ЗаписатьВЛог("Идентификатор устройства получен: " + ИдентификаторУстройства);

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

---

Вариант 2. Использование Идентификатора подписчика уведомлений (FCM / APNs)

Интересный обходной путь заключается в использовании токена службы доставки push-уведомлений. Этот идентификатор можно получить при интеграции мобильного приложения с сервисами рассылки (Google Firebase Cloud Messaging для Android и Apple Push Notification service для iOS).

Давайте проанализируем пример кода для получения этого идентификатора:


ИдентификаторПодписчикаУведомлений = МенеджерДоставляемыхУведомлений.ПолучитьИдентификаторПодписчикаУведомлений(GoogleProjectID);
Если ИдентификаторПодписчикаУведомлений <> Неопределено Тогда
    ИдентификаторУстройства = ИдентификаторПодписчикаУведомлений.ИдентификаторУстройства;
КонецЕсли;

У этого метода есть свои уникальные особенности, о которых необходимо знать заранее:

  1. Квест с настройкой проекта: Для работы этого метода вам потребуется зарегистрировать приложение в консоли Google Firebase, получить уникальный идентификатор проекта (GoogleProjectID) и корректно прописать его при сборке мобильного приложения в сборщике мобильных приложений 1С.
  2. Стабильность кэша: Как отмечают разработчики на практике, старые идентификаторы подписчиков уведомлений могут некоторое время храниться в кэше мобильного устройства. Если у вас настроен регулярный двусторонний обмен данными между мобильным устройством и центральной базой, система может выявить факт изменения идентификатора и корректно "перепривязать" его на стороне сервера, не прерывая работу пользователя.
  3. Проблема истечения токена: Токен push-уведомлений не является постоянным. Он может измениться в любой момент по инициативе серверов Google или Apple (например, при обновлении сервисов Google Play на устройстве, сбросе сетевых настроек, долгом отсутствии устройства в сети или восстановлении операционной системы из резервной копии). Поэтому использовать его в качестве основного ключа синхронизации в СУБД крайне не рекомендуется.

---

Вариант 3. Использование Android ID (SSAID) через внешние компоненты

Для устройств под управлением 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С мы сможем обращаться к ней как к обычному объекту и получать стабильный идентификатор устройства.

---

Вариант 4. Генерация собственного UUID и его сохранение в системных хранилищах

Если мы хотим полностью контролировать процесс идентификации, мы можем самостоятельно сгенерировать уникальный идентификатор при первом запуске приложения с помощью встроенной функции платформы 1С:

НовыйID = Новый УникальныйИдентификатор;

Главная проблема этого подхода — как сохранить этот идентификатор так, чтобы он не удалился при переустановке приложения или очистке данных. Решить эту задачу можно с помощью системных механизмов операционных систем:

---

Рекомендуемая современная архитектура: разделение понятий "Устройство" и "Клиент"

Проанализировав все технические ограничения, мы должны прийти к важному выводу: пытаться жестко идентифицировать физическое устройство без ведома пользователя — это тупиковый путь развития мобильной разработки. Современные стандарты безопасности требуют от нас разделения физического устройства и логического понятия "Пользователь" (или "Клиент").

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

Шаг 1. Проверка авторизации при запуске приложения

При первом запуске мобильного приложения мы проверяем, сохранены ли в локальных настройках параметры авторизации (токен доступа и UUID). Если настроек нет, мы запускаем "Мастер регистрации".


// Процедура ПриНачалеРаботыСистемы мобильного приложения
ПараметрыАвторизации = ПолучитьЛокальныеПараметрыАвторизации(); // Чтение из констант или файлов
Если Не ПараметрыАвторизации.Авторизован Тогда
    ОткрытьФорму("ОбщаяФорма.ФормаРегистрацииПользователя");
КонецЕсли;

Шаг 2. Запрос номера телефона и отправка кода подтверждения

В форме регистрации мы предлагаем пользователю ввести свой номер телефона. Это самый надежный способ идентификации конкретного человека. После ввода номера приложение отправляет запрос на наш центральный сервер 1С.

Центральный сервер генерирует случайный проверочный код (например, из 4 цифр) и отправляет его пользователю на телефон через SMS-шлюз, мессенджер Telegram или посредством звонка-сброса (Flash Call).

Шаг 3. Подтверждение номера и связывание на сервере

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

Давайте посмотрим на примерную схему обработки этого процесса на центральном сервере 1С:


Процедура ПодтвердитьРегистрациюНаСервере(НомерТелефона, КодПодтверждения, ИдентификаторУстройства) Экспорт
    // Проверяем код подтверждения в базе данных сервера
    Если ПроверитьКод(НомерТелефона, КодПодтверждения) Тогда
        // Находим существующего контрагента/физлицо по номеру телефона
        СсылкаНаКлиента = Справочники.Контрагенты.НайтиПоРеквизиту("НомерТелефона", НомерТелефона);
        
        Если СсылкаНаКлиента.Пустая() Тогда
            // Создаем нового клиента, если это первая регистрация
            СсылкаНаКлиента = Справочники.Контрагенты.СоздатьЭлемент();
            СсылкаНаКлиента.Наименование = "Новый клиент " + НомерТелефона;
            СсылкаНаКлиента.НомерТелефона = НомерТелефона;
            СсылкаНаКлиента.Записать();
        КонецЕсли;
        
        // Регистрируем связку Клиент - Устройство в регистре сведений
        МенеджерЗаписи = РегистрыСведений.МобильныеУстройстваКлиентов.СоздатьМенеджерЗаписи();
        МенеджерЗаписи.ИдентификаторУстройства = ИдентификаторУстройства;
        МенеджерЗаписи.Клиент = СсылкаНаКлиента;
        МенеджерЗаписи.ДатаРегистрации = ТекущаяДата();
        МенеджерЗаписи.Активно = Истина;
        МенеджерЗаписи.Записать();
        
        ОтправитьМобильномуКлиентуТокенДоступа(ИдентификаторУстройства);
    Иначе
        ВызватьИсключение "Неверный код подтверждения!";
    КонецЕсли;
КонецПроцедуры

Преимущества такой архитектуры:

Используя этот комплексный подход, мы обеспечиваем максимальную стабильность обмена данными и создаем безопасное, современное мобильное решение на платформе 1С:Предприятие.

← На главную