Развертывание публичных демонстрационных баз 1С, доступных через веб-клиент, накладывает на разработчика ряд специфических задач. С одной стороны, пользователям нужно предоставить максимально простой и бесшовный вход (желательно в один клик через сторонние сервисы по протоколам OAuth 2.0 / OpenID Connect). С другой стороны, необходимо автоматически создавать учетные записи для новых гостей «на лету», строго контролировать выделенный пул лицензий, вести детальные логи посещений и принудительно завершать неактивные сеансы.
В этой статье мы подробно разберем, как спроектировать надежную архитектуру авторизации, обойти ограничения платформы при автоматическом создании пользователей, настроить штатный механизм OpenID Connect и реализовать автоматический менеджмент сессий.
Рассмотрим популярную ошибку проектирования. На первый взгляд кажется заманчивой идея напрямую записывать данные новых пользователей в СУБД (например, в системную таблицу users MS SQL или PostgreSQL). Проанализируем, почему делать этого категорически нельзя:
Единственным верным и безопасным путем является использование промежуточного шлюза авторизации (Proxy / Gatekeeper) в связке с официальным прикладным программным интерфейсом платформы (API). Схема взаимодействия выглядит следующим образом:
HTTP-сервис.Современные версии платформы 1С:Предприятие (начиная с 8.3.22) поддерживают полноценный протокол OpenID Connect «из коробки» на уровне веб-сервера. Нам больше не нужно писать собственные сложные парсеры токенов на стороне 1С. Для интеграции веб-клиента с вашим провайдером авторизации (например, Keycloak) необходимо отредактировать файл публикации базы данных default.vrd.
Рассмотрим пример конфигурации блока <openidconnect> в файле default.vrd:
<openidconnect>
<enabled>true</enabled>
<issuer>https://auth.mycompany.ru/auth/realms/demo</issuer>
<clientId>1c-web-client</clientId>
<clientSecret>your-client-secret-key</clientSecret>
<usernameClaim>email</usernameClaim>
</openidconnect>
Разберем параметры конфигурации подробнее:
issuer — адрес вашего провайдера авторизации (IdP), предоставляющего метаданные OIDC.clientId — идентификатор клиента 1С, зарегистрированный в панели управления IdP.usernameClaim — поле в JWT-токене, значение которого платформа будет сопоставлять с именем пользователя в 1С (в нашем примере это email).В самой 1С у пользователей должен быть установлен флаг «Аутентификация OpenID Connect». Начиная с версии 8.3.22, вы также можете использовать программное свойство КлючиСопоставленияПользователя, чтобы гибко связывать одну учетную запись 1С с различными идентификаторами из внешних систем.
Поскольку сама платформа 1С не умеет автоматически создавать пользователей в БД при первом входе через OIDC (если пользователя нет в списке, система выдаст ошибку авторизации), нам необходимо автоматизировать этот процесс. Для этого создадим в конфигурации 1С специальный HTTP-сервис.
Посмотрим на пример кода метода POST нашего HTTP-сервиса, который принимает данные пользователя от шлюза авторизации и создает учетную запись программными средствами 1С:
Функция СоздатьИлиОбновитьПользователя(Запрос)
// Десериализуем входящий JSON с данными пользователя
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
ДанныеПользователя = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
ИмяПользователя = СокрЛП(ДанныеПользователя.Email);
ПолноеИмя = СокрЛП(ДанныеПользователя.FullName);
Если ПустаяСтрока(ИмяПользователя) Тогда
Ответ = Новый HTTPСервисОтвет(400);
Ответ.УстановитьТелоИзСтроки("Не указан Email пользователя");
Возврат Ответ;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
// 1. Создаем пользователя информационной базы (системный уровень)
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователя);
Если ПользовательИБ = Неопределено Тогда
ПользовательИБ = ПользователиИнформационнойБазы.СоздатьПользователя();
КонецЕсли;
ПользовательИБ.Имя = ИмяПользователя;
ПользовательИБ.ПолноеИмя = ПолноеИмя;
ПользовательИБ.АутентификацияOpenIDConnect = Истина;
ПользовательИБ.АутентификацияСтандартная = Ложь;
ПользовательИБ.ПоказыватьВСпискеВыбора = Ложь;
// Назначаем базовую роль для демо-входа
РольДемо = Метаданные.Роли.ДемоДоступ;
Если ПользовательИБ.Роли.Содержит(РольДемо) = Ложь Тогда
ПользовательИБ.Роли.Добавить(РольДемо);
КонецЕсли;
Попытка
ПользовательИБ.Записать();
Исключение
ЗаписьЖурналаРегистрации("АвторизацияOIDC", УровеньЖурналаРегистрации.Ошибка,,,
"Ошибка создания пользователя ИБ: " + ОписаниеОшибки());
Ответ = Новый HTTPСервисОтвет(500);
Возврат Ответ;
КонецПопытки;
// 2. Создаем или обновляем элемент в прикладном справочнике "Пользователи" (если применимо)
// Разберем этот шаг, так как большинство типовых конфигураций (БСП) требуют наличия элемента в справочнике
СсылкаНаПользователя = Справочники.Пользователи.НайтиПоРеквизиту("ИдентификаторПользователяИБ", ПользовательИБ.УникальныйИдентификатор);
Если СсылкаНаПользователя.Пустая() Тогда
НовыйПользовательСпр = Справочники.Пользователи.СоздатьЭлемент();
НовыйПользовательСпр.Наименование = ПолноеИмя;
НовыйПользовательСпр.ИдентификаторПользователяИБ = ПользовательИБ.UuID; // Для версий БСП
НовыйПользовательСпр.Записать();
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки("Пользователь успешно подготовлен");
Возврат Ответ;
КонецФункции
В сценарии с публичной демонстрационной базой количество доступных лицензий всегда ограничено. Если наплыв пользователей велик, мы рискуем быстро исчерпать весь пул клиентских лицензий, из-за чего новые клиенты увидят системное окно об ошибке. Рассмотрим, как эффективно управлять лицензиями и сессиями.
Шаг 1. Настройка времени засыпания и завершения неактивных сеансов в веб-публикации.
Самый простой способ освободить зависшие лицензии — настроить автоматическое усыпление неактивных веб-клиентов. В том же файле default.vrd внутри секции <point> мы можем настроить параметры времени жизни сессий:
<point ...>
<sessionMaxAge>1200</sessionMaxAge>
<sessionTimeout>300</sessionTimeout>
</point>
sessionTimeout — время в секундах (в нашем примере 5 минут), по истечении которого неактивный сеанс веб-клиента «засыпает» и освобождает лицензию обратно в пул сервера.sessionMaxAge — максимальное время жизни «спящей» сессии в секундах (в нашем примере 20 минут), после чего сервер полностью удалит ее из памяти.Шаг 2. Использование возможностей самообслуживания платформы (8.3.24+).
Начиная с версии платформы 8.3.24, встроенный механизм управления сеансами позволяет выводить пользователю информационное окно со списком его прошлых «зависших» сессий при повторном входе. Пользователь может самостоятельно нажать кнопку завершения старой сессии, чтобы войти в систему под освободившейся лицензией.
Шаг 3. Жесткое вытеснение пользователей через RAS/RAC.
Если нам необходимо принудительно контролировать общее количество активных пользователей в демо-базе и кикать тех, кто превысил лимит времени (например, давать каждому пользователю ровно 30 минут на ознакомление), мы должны задействовать сервер администрирования 1С (RAS) и консольную утилиту RAC.
Мы можем написать скрипт (например, на Python или PowerShell) на сервере приложений, который будет запускаться по расписанию раз в минуту. Алгоритм работы скрипта:
rac session list --cluster=<ИД_Кластера> --infobase=<ИД_Базы>started-at (время запуска сеанса) и last-active-at (время последней активности).rac session terminate --cluster=<ИД_Кластера> --session=<ИД_Сеанса>Для предотвращения злоупотреблений и сбора статистики по потенциальным клиентам критически важно фиксировать, кто, когда и откуда заходил в систему. Для этого в кодовой базе 1С мы можем переопределить стандартное событие при старте системы.
В модуле управляемого приложения проанализируем ситуацию в процедуре ПриНачалеРаботыСистемы:
Процедура ПриНачалеРаботыСистемы()
// Проверим, что сеанс открыт именно через веб-клиент
#Если ВебКлиент Тогда
// Зафиксируем событие в Журнале Регистрации
ИмяТекущегоПользователя = ПользователиИнформационнойБазы.ТекущийПользователь().Имя;
ПараметрыЗаписи = Новый Структура;
ПараметрыЗаписи.Вставить("Пользователь", ИмяТекущегоПользователя);
ПараметрыЗаписи.Вставить("ВремяВхода", ТекущаяДата());
ЗаписьЖурналаРегистрации(
"ДемоДоступ.ВходПользователя",
УровеньЖурналаРегистрации.Информация,
Метаданные.HTTPСервисы.ДемоАвторизация, // Связываем с метаданными сервиса
,
"Пользователь " + ИмяТекущегоПользователя + " успешно зашел в веб-клиент."
);
#КонецЕсли
КонецПроцедуры
Спроектированное таким образом решение гарантирует стабильную, безопасную и полностью легальную работу демонстрационной базы 1С с авторизацией по современным протоколам OpenID Connect / OAuth 2.0. Вы сможете гибко масштабировать пул лицензий, автоматически регистрировать пользователей и не беспокоиться о зависших сессиях веб-клиентов.