Как программно определить тип аутентификации пользователя и проверить корректность входа через Windows

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

В процессе администрирования сложных систем на базе 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

Если нам нужно не просто узнать, как зашел пользователь, но и понять, почему ОС-аутентификация не сработала (например, учетная запись заблокирована в домене), мы можем выполнить запрос к Active Directory через провайдер WinNT или LDAP. Это поможет выявить проблему еще до того, как пользователь столкнется с ошибкой при попытке создать COMОбъект.

Пример функции для проверки существования и доступности учетной записи в домене:


Функция ПроверитьДоступностьУчеткиОС(ПутьКПользователюОС) Экспорт
    // Формат пути: \\DomainName\UserName
    ИмяПути = СтрЗаменить(СокрЛП(ПутьКПользователюОС), "\", "/");
    Если Лев(ИмяПути, 2) = "//" Тогда
        ИмяПути = Сред(ИмяПути, 3);
    КонецЕсли;
    
    Попытка
        // Пытаемся подключиться к объекту пользователя в домене
        ПользовательAD = ПолучитьCOMОбъект("WinNT:/" + ИмяПути + ",user");
        
        // Проверяем, не заблокирована ли учетка
        Если ПользовательAD.AccountDisabled Тогда
            Возврат "Учетная запись заблокирована в домене";
        КонецЕсли;
        
        Возврат "ОК";
    Исключение
        Возврат "Пользователь ОС не найден или нет доступа к контроллеру домена";
    КонецПопытки;
КонецФункции

Итоговый алгоритм мониторинга

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

  1. В процедуре ПриНачалеРаботыСистемы определим, включена ли для текущего пользователя ОС-аутентификация в настройках ИБ.
  2. С помощью WScript.Network или анализа Журнала регистрации получим фактический способ входа.
  3. Если в настройках вход по ОС разрешен, но фактически пользователь зашел по паролю 1С — выполним диагностику:
    • Проверим соответствие имени текущего пользователя Windows тому значению, которое прописано в 1С.
    • Проверим доступность доменного контроллера.
  4. Запишем результат диагностики в Журнал регистрации с уровнем Предупреждение.

Такой подход позволит системным администраторам оперативно реагировать на изменения в доменной структуре (например, переименование доменов или миграция учетных записей), не дожидаясь жалоб пользователей на неработающие обмены данными через COM-соединения.

Важное замечание: помните, что при работе в терминальном режиме (RDP) стандартная функция ИмяКомпьютера() вернет имя сервера. Для идентификации конкретного рабочего места пользователя лучше считывать переменную окружения CLIENTNAME, которая содержит имя локального ПК, с которого установлено соединение.

← На главную