В процессе разработки часто возникает задача определить конкретного пользователя в справочнике Пользователи, имея на руках только строковое представление его логина в операционной системе (например, «domain\user»). Сложность заключается в том, что в типовой платформе 1С:Предприятие 8 данные об аутентификации ОС хранятся в объектах ПользовательИнформационнойБазы, которые не являются ссылочными данными и к которым нельзя обратиться через обычный запрос SELECT.
В этой статье мы разберем, как связать данные операционной системы с объектами информационной базы, проанализируем программные способы поиска и рассмотрим методы оптимизации, чтобы избежать проблем с производительностью.
Для начала разберем важный архитектурный нюанс. В 1С существует два уровня сущностей:
ВЫБРАТЬ.ИдентификаторПользователяИБ (тип УникальныйИдентификатор), который служит ключом для связи со вторым уровнем.Наша задача — найти Пользователя ИБ, у которого свойство ПользовательОС совпадает с искомой строкой, получить его УникальныйИдентификатор и по нему найти ссылку в справочнике.
Поскольку платформа не предоставляет метода НайтиПоРеквизиту для списка пользователей информационной базы (кроме поиска по имени и полному идентификатору), нам придется использовать метод ПолучитьПользователей(). Проанализируем пример кода, который решает эту задачу:
// Искомая строка (Curator), например: "Windows:DOMAIN\UserName"
ПользователиИБ = ПользователиИнформационнойБазы.ПолучитьПользователей();
СсылкаНаПользователя = Справочники.Пользователи.ПустаяСсылка();
Для Каждого ПользовательИБ Из ПользователиИБ Цикл
// Сравниваем свойство ПользовательОС с нашей строкой
Если ПользовательИБ.ПользовательОС = Curator Тогда
// Когда соответствие найдено, ищем ссылку в справочнике по UUID
СсылкаНаПользователя = Справочники.Пользователи.НайтиПоРеквизиту("ИдентификаторПользователяИБ", ПользовательИБ.УникальныйИдентификатор);
Прервать; // Выходим из цикла, так как пользователь найден
КонецЕсли;
КонецЦикла;
Если НЕ СсылкаНаПользователя.Пустая() Тогда
// Дальнейшая логика работы с найденным пользователем
КонецЕсли;
В данном примере мы сначала выгружаем весь список пользователей системы в массив, а затем в цикле ищем совпадение по свойству ПользовательОС. Как только совпадение найдено, мы используем УникальныйИдентификатор системного пользователя для поиска элемента в справочнике Пользователи.
Проанализируем ситуацию, когда сравнение ПользовательИБ.ПользовательОС = Curator может не сработать. Платформа 1С хранит данные аутентификации в специфических форматах. Обычно это:
Windows:<домен>\<имя>WinNT://<домен>/<имя>Если в вашей переменной Curator просто записано «domain\user», прямое равенство выдаст Ложь. Рекомендуется перед поиском приводить строку к нужному формату или использовать функцию СтрНайти, хотя это может быть чуть медленнее. Также учитывайте, что в некоторых конфигурациях (особенно на Linux-серверах) регистр символов может иметь значение.
Рассмотрим подробнее работу метода ПользователиИнформационнойБазы.ПолучитьПользователей(). Этот метод при каждом вызове обращается к системным таблицам и считывает данные всех пользователей. Если в вашей базе 10–20 пользователей, вы не заметите задержек. Однако в крупных корпоративных системах, где количество пользователей исчисляется сотнями или тысячами, этот вызов может занимать несколько секунд.
Критически важно: не вызывайте этот код внутри циклов обработки документов или при записи каждой строки большой таблицы. Если вам нужно найти 100 кураторов для 100 договоров, лучше один раз получить список пользователей ИБ, выгрузить его в ТаблицуЗначений или Соответствие, и далее искать уже в подготовленном кэше в памяти.
Если задача поиска пользователя по ОС возникает регулярно (например, при импорте данных или автоматическом распределении задач), правильнее будет изменить структуру данных. Разберем, как это сделать:
Пользователи собственный индексированный реквизит ИмяПользователяОС (строка).
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Пользователи.Ссылка КАК Ссылка
|ИЗ
| Справочник.Пользователи КАК Пользователи
|ГДЕ
| Пользователи.ИмяПользователяОС = &ИмяОС
| И НЕ Пользователи.ПометкаУдаления";
Запрос.УстановитьПараметр("ИмяОС", ИскомыйЛогин);
Результат = Запрос.Выполнить();
Если ваша конфигурация построена на Библиотеке Стандартных Подсистем (БСП), выясним, как упростить задачу. В БСП существует общий модуль Пользователи. Хотя прямого поиска по ОС там может не быть, полезно использовать методы для получения идентификаторов:
Идентификатор = Пользователи.ИдентификаторПользователяИБ(НужныйПользователь);
Это гарантирует корректную работу с уникальными идентификаторами, которые могут отличаться в разных версиях платформы.
Для разовой задачи или небольшой базы метод с перебором ПолучитьПользователей() вполне допустим и прост в реализации. Однако для высоконагруженных систем или частых операций поиска всегда стремитесь к кэшированию данных в справочнике или регистре сведений, чтобы использовать мощь SQL-запросов вместо линейного перебора в коде 1С.