Как настроить авторизацию доменного пользователя при работе с WS-ссылками в 1С

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

При интеграции систем через веб-сервисы разработчики часто сталкиваются с ситуацией, когда стандартный механизм WSПрокси отказывается работать с корпоративными серверами, требующими доменной авторизации (NTLM или Negotiate). Типичный симптом: при попытке вызова метода сервиса возвращается ошибка 401 Unauthorized, хотя логин и пароль указаны верно. Проанализируем, почему это происходит, и разберем по шагам, как реализовать надежное соединение.

Почему стандартный WSПрокси может не работать

Проблема кроется в механизме "рукопожатия" (handshake) протоколов доменной авторизации. В отличие от простой (Basic) авторизации, где логин и пароль передаются в одном заголовке, NTLM требует нескольких итераций обмена данными. Проанализируем типичный цикл обмена:

  1. Клиент отправляет запрос без заголовков.
  2. Сервер отвечает кодом 401 и заголовком WWW-Authenticate: NTLM (или Negotiate).
  3. Клиент отправляет запрос с временным токеном.
  4. Сервер отвечает очередным токеном и устанавливает сессионную куку (Set-Cookie).
  5. Клиент подтверждает авторизацию и передает куку.

В некоторых версиях платформы 1С объект WSПрокси не всегда корректно удерживает контекст сессии (куки) между этими этапами, особенно если WSDL-описание подгружается динамически. В то же время объект HTTPСоединение справляется с этой задачей гораздо стабильнее.

Способ 1. Правильная настройка WSПрокси и защищенного соединения

Прежде чем переходить к сложным обходным путям, проверим, все ли параметры WSПрокси заданы корректно. Важно использовать ЗащищенноеСоединениеOpenSSL с явным указанием использования сертификатов ОС, если речь идет о защищенном канале (HTTPS).

Рассмотрим пример кода, который часто помогает решить проблему "в лоб":


// Настраиваем защищенное соединение с использованием системных сертификатов
SSL = Новый ЗащищенноеСоединениеOpenSSL(
    Новый СертификатКлиентаWindows(), 
    Новый СертификатыУдостоверяющихЦентровWindows()
);

// Сначала создаем определения. Если WSDL защищен, логин/пароль передаем и сюда
Определение = Новый WSОпределения(МестоположениеWSDL, Логин, Пароль, , , SSL);

// Инициализируем прокси. 
// Параметр "ИспользоватьАутентификациюОС" (последний в конструкторе) 
// при значении Истина задействует текущего пользователя Windows.
Прокси = Новый WSПрокси(
    Определение, 
    ПространствоИмен, 
    ИмяСервиса, 
    ИмяТочкиПодключения, 
    , 
    , 
    SSL, 
    , 
    Истина // ИспользоватьАутентификациюОС
);

// Если авторизация нужна под конкретным (другим) доменным пользователем:
Прокси.Пользователь = "DOMAIN\UserName";
Прокси.Пароль = "UserPassword";

Важный нюанс: Если код выполняется на стороне сервера 1С, под "текущим пользователем" подразумевается учетная запись, от имени которой запущена служба 1C:Enterprise 8.3 Server Agent. Обычно это локальный пользователь USR1CV8, у которого нет прав в домене. В этом случае использование ИспользоватьАутентификациюОС = Истина не даст результата, и нужно передавать явные учетные данные.

Способ 2. Гибридный метод (HTTP + XDTO)

Если WSПрокси все равно выдает 401, применим более продвинутый метод. Мы будем использовать HTTPСоединение для транспортного уровня (так как оно лучше работает с авторизацией) и ФабрикуXDTO для парсинга ответа, чтобы не заниматься разбором XML вручную. Выясним, как это реализовать.

Шаг 1. Создаем структуру через WSОпределения. Мы можем загрузить WSDL из локального файла, который предварительно скачали браузером или через HTTPСоединение.


// Загружаем схему из файла для получения типов данных
Определения = Новый WSОпределения("C:\WebServices\service.wsdl");
Фабрика = Определения.ФабрикаXDTO;

Шаг 2. Выполняем запрос через HTTPСоединение. Сформируем SOAP-пакет вручную. Это всего лишь XML-строка определенного формата.


Сервер = "api.company.com";
Ресурс = "/v1/service";

// Настройка соединения с явной доменной авторизацией
Соединение = Новый HTTPСоединение(
    Сервер, , 
    "DOMAIN\User", "Password", 
    , , 
    Новый ЗащищенноеСоединениеOpenSSL(), 
    Истина // Использовать аутентификацию ОС
);

// Формируем тело SOAP-запроса
ТекстЗапроса = 
"<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
|  <soap:Body>
|    <m:GetPrice xmlns:m=""http://www.company.com/schema"">
|      <m:ItemCode>12345</m:ItemCode>
|    </m:GetPrice>
|  </soap:Body>
|</soap:Envelope>";

Запрос = Новый HTTPЗапрос(Ресурс);
Запрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
Запрос.Заголовки.Вставить("SOAPAction", "http://www.company.com/action/GetPrice");
Запрос.УстановитьТелоИзСтроки(ТекстЗапроса);

Ответ = Соединение.ОтправитьДляОбъекта(Запрос);

Шаг 3. Превращаем XML в объект 1С. Вместо поиска подстрок в тексте ответа, используем механизмы XDTO. Проанализируем, как десериализовать полученный XML:


Если Ответ.КодСостояния = 200 Тогда
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
    
    // Пропускаем конверт SOAP до тела сообщения
    ЧтениеXML.ПерейтиКСодержимому(); 
    Пока ЧтениеXML.Прочитать() Цикл
        Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.ЛокальноеИмя = "GetPriceResponse" Тогда
            // Читаем данные напрямую в объект XDTO
            ТипОбъекта = Фабрика.Тип("http://www.company.com/schema", "PriceResult");
            РезультатXDTO = Фабрика.ПрочитатьXML(ЧтениеXML, ТипОбъекта);
            
            // Теперь мы можем обращаться к данным как к свойствам объекта
            Сообщить("Цена: " + РезультатXDTO.Amount);
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецЕсли;

Рекомендации по отладке

Проанализируем ситуацию, если авторизация все равно не проходит. Рассмотрим основные точки контроля:

Таким образом, если стандартный объект WSПрокси не справляется с авторизацией, использование связки HTTPСоединение и ФабрикаXDTO является наиболее надежным и гибким решением, позволяющим сохранить все преимущества типизации данных 1С при стабильном транспортном канале.

← На главную