В процессе администрирования сложных систем на базе 1С:Предприятие часто возникает ситуация, когда пользователям разрешена как ОС-аутентификация (автоматический вход под доменной учетной записью), так и 1С-аутентификация (вход по логину и паролю). Однако для корректной работы некоторых механизмов, таких как COM-соединения между базами, критически важно, чтобы пользователь авторизовался именно через операционную систему. Если доменная политика меняется или возникают проблемы с сетью, пользователь может «проскочить» в базу, введя пароль вручную, что позже приведет к ошибкам интеграции. В этой статье мы разберем, как программно определить, каким именно способом зашел пользователь, и зафиксировать это в Журнале регистрации.
Для начала разберем стандартный метод получения настроек пользователя. С помощью объекта ПользовательИнформационнойБазы мы можем узнать, какие способы входа разрешены для конкретного сотрудника. Рассмотрим пример кода, который позволяет получить эти данные на сервере:
// Функция возвращает настройки аутентификации пользователя ИБ
Функция ПолучитьНастройкиАутентификации(ПользовательСсылка) Экспорт
ИмяПользователяИБ = ПользовательСсылка.Наименование; // Или другой реквизит, хранящий логин
ПользовательИБ = ПользователиИнформационнойБазы.НайтиПоИмени(ИмяПользователяИБ);
Если ПользовательИБ = Неопределено Тогда
Возврат "Пользователь не найден в ИБ";
КонецЕсли;
Результат = Новый Структура;
Результат.Вставить("АутентификацияОС", ПользовательИБ.АутентификацияОС);
Результат.Вставить("ПользовательОС", ПользовательИБ.ПользовательОС);
Результат.Вставить("АутентификацияСтандартная", ПользовательИБ.АутентификацияСтандартная);
Возврат Результат;
КонецФункции
Проанализируем этот код: свойство АутентификацияОС возвращает Истина, если в конфигураторе установлена соответствующая галочка. Однако это не означает, что пользователь зашел именно по ней. Это лишь разрешение на такой тип входа. Чтобы понять реальную картину, нам нужно сопоставить эти настройки с фактическими данными текущего сеанса.
Чтобы выяснить, под какой учетной записью Windows работает запущенный экземпляр 1С, мы можем воспользоваться возможностями операционной системы через COM-объекты. Это наиболее простой и быстрый способ, работающий на стороне клиента. Разберем использование объекта WScript.Network.
// Метод получения текущего доменного имени пользователя
Функция ПолучитьТекущегоПользователяWindows() Экспорт
Попытка
Сеть = Новый COMОбъект("WScript.Network");
Домен = Сеть.UserDomain;
Логин = Сеть.UserName;
Возврат ВРег(Домен + "\" + Логин);
Исключение
// Если COM-объект недоступен, попробуем через переменные окружения
Домен = ПолучитьПеременнуюОкружения("USERDOMAIN");
Логин = ПолучитьПеременнуюОкружения("USERNAME");
Возврат ВРег(Домен + "\" + Логин);
КонецПопытки;
КонецФункции
Используя этот метод в процедуре ПриНачалеРаботыСистемы, мы можем сравнить полученную строку с тем, что прописано в настройках ПользовательИБ.ПользовательОС. Если настройки требуют вход под DOMAIN\User1, а системный объект вернул то же самое значение — с высокой долей вероятности ОС-аутентификация отработала штатно.
Наиболее достоверный способ определить тип входа — это анализ системного события аутентификации, которое 1С записывает в Журнал регистрации при каждом старте сеанса. В платформе 8.3 это событие имеет внутренний идентификатор _$Session$_.Authentication. Проанализируем, как программно выгрузить эти данные для текущего сеанса.
Процедура ПроверитьТипВходаИЗаписатьВЖурнал(Пользователь) Экспорт
// Получаем номер текущего сеанса
НомерСеанса = НомерСеансаИнформационнойБазы();
// Настраиваем фильтр для Журнала регистрации
Фильтр = Новый Структура;
Фильтр.Вставить("Событие", "_$Session$_.Authentication");
Фильтр.Вставить("Сеанс", НомерСеанса);
ТЗ_Лог = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(ТЗ_Лог, Фильтр, "Дата, Данные, Пользователь");
// Сортируем, чтобы найти самое раннее событие входа в этом сеансе
ТЗ_Лог.Сортировать("Дата Возр");
Если ТЗ_Лог.Количество() > 0 Тогда
Запись = ТЗ_Лог[0];
// В поле "Данные" содержится структура с подробностями
Если ТипЗнч(Запись.Данные) = Тип("Структура") Тогда
ТекущийОС = "";
Если Запись.Данные.Свойство("ТекущийПользовательОС", ТекущийОС) Тогда
// Если свойство заполнено, значит платформа опознала пользователя ОС
ТипАутентификации = "ОС-аутентификация";
Иначе
ТипАутентификации = "1С-аутентификация (пароль)";
КонецЕсли;
// Записываем информационное сообщение для администратора
ЗаписьЖурналаРегистрации("МониторингВхода",
УровеньЖурналаРегистрации.Информация, , ,
"Пользователь: " + Пользователь + " зашел через " + ТипАутентификации +
". Фактический пользователь ОС: " + ТекущийОС);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рассмотрим важный нюанс: метод ВыгрузитьЖурналРегистрации может быть ресурсоемким. Чтобы не замедлять работу системы, рекомендуется выполнять этот поиск только один раз при старте или использовать ограничение по времени (например, анализировать записи только за последние 5 минут).
Если нам нужно не просто узнать, как зашел пользователь, но и понять, почему ОС-аутентификация не сработала (например, учетная запись заблокирована в домене), мы можем выполнить запрос к Active Directory через провайдер WinNT или LDAP. Это поможет выявить проблему еще до того, как пользователь столкнется с ошибкой при попытке создать COMОбъект.
Пример функции для проверки существования и доступности учетной записи в домене:
Функция ПроверитьДоступностьУчеткиОС(ПутьКПользователюОС) Экспорт
// Формат пути: \\DomainName\UserName
ИмяПути = СтрЗаменить(СокрЛП(ПутьКПользователюОС), "\", "/");
Если Лев(ИмяПути, 2) = "//" Тогда
ИмяПути = Сред(ИмяПути, 3);
КонецЕсли;
Попытка
// Пытаемся подключиться к объекту пользователя в домене
ПользовательAD = ПолучитьCOMОбъект("WinNT:/" + ИмяПути + ",user");
// Проверяем, не заблокирована ли учетка
Если ПользовательAD.AccountDisabled Тогда
Возврат "Учетная запись заблокирована в домене";
КонецЕсли;
Возврат "ОК";
Исключение
Возврат "Пользователь ОС не найден или нет доступа к контроллеру домена";
КонецПопытки;
КонецФункции
Для реализации полноценного контроля за типами аутентификации в вашей конфигурации, рекомендуем придерживаться следующего алгоритма в модуле управляемого приложения:
ПриНачалеРаботыСистемы определим, включена ли для текущего пользователя ОС-аутентификация в настройках ИБ.WScript.Network или анализа Журнала регистрации получим фактический способ входа.Такой подход позволит системным администраторам оперативно реагировать на изменения в доменной структуре (например, переименование доменов или миграция учетных записей), не дожидаясь жалоб пользователей на неработающие обмены данными через COM-соединения.
Важное замечание: помните, что при работе в терминальном режиме (RDP) стандартная функция ИмяКомпьютера() вернет имя сервера. Для идентификации конкретного рабочего места пользователя лучше считывать переменную окружения CLIENTNAME, которая содержит имя локального ПК, с которого установлено соединение.