Как предотвратить появление окна авторизации при обращении к веб-серверу с Windows-аутентификацией

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

При разработке интеграционных решений на платформе 1С:Предприятие часто возникает ситуация, когда необходимо обратиться к веб-сервису, защищенному с помощью Windows-аутентификации. Стандартное поведение системы в этом случае может преподнести сюрприз: вместо того чтобы просто вернуть код ошибки 401 (Unauthorized) в программный код, операционная система перехватывает управление и выводит пользователю диалоговое окно для ввода логина и пароля. Это блокирует автоматизацию процесса и вынуждает пользователя совершать лишние действия, такие как нажатие кнопки "Отмена".

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

Причина возникновения проблемы: WinInet против WinHTTP

Для начала проанализируем ситуацию. Когда мы используем COM-объект MSXML2.XMLHTTP.6.0, мы фактически работаем через библиотеку WinInet. Эта библиотека изначально проектировалась для браузера Internet Explorer. Её главная задача — обеспечить интерактивное взаимодействие с пользователем. Если сервер запрашивает авторизацию (отправляет заголовок WWW-Authenticate), WinInet считает своим долгом помочь пользователю и выводит системное окно ввода учетных данных.

Если же наша задача — реализовать "тихий" запрос, который должен либо выполниться под текущим пользователем ОС, либо вернуть 401 для дальнейшей обработки логикой 1С, нам нужно либо сменить инструмент, либо изменить настройки текущего.

Решение 1. Использование встроенного объекта 1С HTTPСоединение

Рассмотрим наиболее правильный способ для современной платформы 1С. Встроенный объект HTTPСоединение обладает параметром, который позволяет управлять Windows-аутентификацией напрямую, не вызывая лишних диалогов. Как отметил автор исходной темы, этот метод является наиболее стабильным.

Разберем пример кода, который позволяет выполнить запрос прозрачно:


// Определяем параметры подключения
Сервер = "myserver.local";
Ресурс = "/MyBase/hs/my_service/v1/data";

// Ключевой момент: параметр ИспользоватьАутентификациюОС = Истина
// Это заставляет 1С использовать текущий токен пользователя Windows
Соединение = Новый HTTPСоединение(Сервер, , , , , , , Истина);

Запрос = Новый HTTPЗапрос(Ресурс);
// Добавляем необходимые заголовки, если нужно
Запрос.Заголовки.Вставить("Content-Type", "application/xml");

Попытка
    Ответ = Соединение.ВызватьHTTPМетод("POST", Запрос);
    КодСостояния = Ответ.КодСостояния;
    
    Если КодСостояния = 200 Тогда
        // Обрабатываем успешный ответ
        Сообщить("Запрос выполнен успешно под пользователем ОС");
    ИначеЕсли КодСостояния = 401 Тогда
        // Окно не появилось, мы получили управление и можем
        // реализовать логику создания пользователя или регистрации
        Сообщить("Пользователь не авторизован, выполняем регистрацию...");
    КонецЕсли;
Исключение
    // Обработка сетевых ошибок
    Сообщить("Ошибка при выполнении запроса: " + ОписаниеОшибки());
КонецПопытки;

Использование HTTPСоединение с флагом ИспользоватьАутентификациюОС решает проблему в большинстве случаев на платформе 8.3. Однако, если ваша конфигурация работает в режиме совместимости со старыми версиями (например, 8.2 или ранние 8.3), этот функционал может быть недоступен или работать некорректно.

Решение 2. Переход на WinHTTP (ServerXMLHTTP)

Если по каким-то причинам вы обязаны использовать COM-объекты (например, при работе в очень старых конфигурациях или специфических окружениях), следует заменить MSXML2.XMLHTTP на MSXML2.ServerXMLHTTP или напрямую на WinHttp.WinHttpRequest.5.1.

Объект ServerXMLHTTP базируется на библиотеке WinHTTP. В отличие от WinInet, она создана для серверных приложений и сервисов. У неё нет интерфейса пользователя, поэтому она физически не может вывести окно ввода пароля. Если аутентификация не удалась, она просто вернет ошибку или код 401.

Проанализируем пример использования WinHttpRequest:


WinHTTP = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
WinHTTP.Open("POST", АдресЗапроса, Ложь);

// Установка политики автоматического входа
// 0 - AutoLogonPolicy_Always
// 1 - AutoLogonPolicy_OnlyIfSensitive
// 2 - AutoLogonPolicy_Never (запретить автоматический вход и окна)
WinHTTP.SetAutoLogonPolicy(2); 

WinHTTP.Send(ТелоЗапроса);
КодОтвета = WinHTTP.Status;

Если КодОтвета = 401 Тогда
    // Мы получили 401 без всяких окон!
    // Здесь ваша логика по созданию пользователя
КонецЕсли;

Метод SetAutoLogonPolicy(2) гарантирует, что объект даже не будет пытаться использовать учетные данные текущего пользователя, что моментально приведет к получению 401 от сервера IIS, если анонимный доступ закрыт.

Решение 3. Использование "фиктивных" учетных данных

Иногда полезно "обмануть" библиотеку WinInet, передав ей пустые или заведомо неверные данные в методе Open. Когда объект видит, что программист уже предоставил учетные данные (даже если они неверны), он часто подавляет попытку вызова системного окна.

Посмотрим на пример модификации исходного кода:


XMLHTTP = Новый COMОбъект("MSXML2.XMLHTTP.6.0");
// Передаем пустые строки в качестве логина и пароля
XMLHTTP.Open("POST", Адрес, Ложь, " ", " "); 
XMLHTTP.Send(Запрос);
КодОтвета = XMLHTTP.Status;

Этот метод менее надежен, чем использование WinHTTP, но в некоторых специфических конфигурациях безопасности Windows он помогает избежать появления окна.

Решение 4. Управление заголовками на стороне сервера и клиента

Существует стандарт де-факто: если запрос является асинхронным (AJAX), сервер не должен запрашивать интерактивную авторизацию. Выясним, как мы можем это использовать. Многие веб-серверы (включая IIS, на котором обычно публикуется 1С) проверяют наличие заголовка X-Requested-With.

Попробуем добавить этот заголовок в наш запрос:

XMLHTTP.setRequestHeader("X-Requested-With", "XMLHttpRequest");

В некоторых случаях правильно настроенный IIS, увидев этот заголовок, при ошибке авторизации отправит чистый код 401 без предложения пройти NTLM/Negotiate проверку в интерактивном режиме.

Рекомендации по настройке IIS

Если вы контролируете сервер, на котором опубликован веб-сервис 1С, проверьте следующие настройки в диспетчере IIS:

  1. Проверка подлинности Windows (Windows Authentication): В расширенных настройках (Advanced Settings) попробуйте включить или выключить "Проверку подлинности в режиме ядра" (Kernel-mode authentication). Иногда её отключение помогает более корректно обрабатывать программные запросы.
  2. Анонимная проверка подлинности: Если ваша логика подразумевает, что сначала нужно "постучаться" анонимно, чтобы получить 401, а потом уже решать, что делать — убедитесь, что анонимный доступ разрешен на уровне IIS, но ограничен на уровне прав доступа к конкретным папкам или приложению 1С.
  3. Зоны безопасности: Помните, что поведение XMLHTTP зависит от настроек "Свойств браузера" в Windows. Если адрес сервера находится в зоне "Местная интрасеть", Windows будет пытаться отправить текущий логин автоматически. Если в зоне "Интернет" — скорее всего, будет запрашивать пароль.

Резюме

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

  1. Первоочередное решение: Используйте встроенный объект 1С HTTPСоединение с параметром ИспользоватьАутентификациюОС = Истина. Это самый современный и поддерживаемый платформой способ.
  2. Если нужна работа через COM: Замените XMLHTTP на WinHttp.WinHttpRequest.5.1 и используйте метод SetAutoLogonPolicy(2). Это полностью исключит появление любых интерфейсных окон.
  3. Если вы ограничены старой версией XMLHTTP: Используйте передачу пустых строк в метод Open и добавление заголовка X-Requested-With.

Выбрав один из этих методов, вы сможете реализовать гибкую логику обработки авторизации, например, автоматическую регистрацию новых пользователей в базе 1С при их первом обращении к веб-сервису под учетной записью Windows.

← На главную