Как в 1С вызвать веб-сервис с аутентификацией Active Directory от имени текущего пользователя

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

При интеграции 1С со сторонними корпоративными системами нередко возникает задача обращения к веб-сервису, настроенному на сквозную доменную аутентификацию Windows (Active Directory, Kerberos/NTLM). При этом требуется, чтобы сторонний сервис авторизовал именно того сотрудника, который в данный момент работает в сеансе 1С, но без явного ввода его сетевого пароля. Рассмотрим подробнее, с какими архитектурными ограничениями платформы 1С здесь приходится сталкиваться, и разберем по шагам рабочие варианты решения этой задачи.

Почему возникает ошибка при стандартном вызове через WSПрокси на сервере

В конструкторе объекта WSПрокси и в методе WSСсылки.СоздатьWSПрокси() разработчикам доступен параметр ИспользоватьАутентификациюОС. Казалось бы, достаточно установить этот флаг в значение Истина, оставить имя пользователя и пароль пустыми, и веб-сервис будет успешно вызван. Однако на практике разработчик сталкивается с неочевидной ошибкой: Ошибка HTTP (чаще всего 401 Unauthorized).

Выясним причину такого поведения системы:

  1. Контекст выполнения серверного кода. В клиент-серверной архитектуре 1С все процедуры с директивой &НаСервере исполняются в контексте рабочего процесса сервера приложений (rphost). Когда на сервере выполняется обращение к внешнему ресурсу с флагом ИспользоватьАутентификациюОС = Истина, операционная система задействует учетную запись, под которой запущена сама служба сервера 1С. Если служба 1С работает под локальной учетной записью (например, usr1cv8), у нее попросту нет прав в домене Active Directory для авторизации на внешнем сервисе.
  2. Отсутствие олицетворения (Impersonation). В платформе 1С:Предприятие отсутствует механизм автоматического сквозного делегирования учетных данных Windows от клиентского приложения к серверному процессу. Сервер приложений 1С не переключает контекст безопасности операционной системы на текущего пользователя тонкого клиента при вызове серверных методов.
  3. Ограничения контекста объектов WS. Объекты WSОпределения и WSПрокси в управляемом приложении не могут быть созданы на стороне тонкого клиента. Они доступны исключительно на сервере, в толстом клиенте или во внешнем соединении. Поэтому вызвать WSПрокси непосредственно на рабочем месте пользователя в режиме тонкого клиента невозможно.

Способ 1. Вызов веб-сервиса через HTTPСоединение на стороне клиента

Разберем наиболее надежный и универсальный обходной путь, который позволяет выполнить запрос от имени залогиненного пользователя Windows без ввода пароля в режиме тонкого клиента. В отличие от WSПрокси, объект HTTPСоединение доступен в контексте &НаКлиенте и полностью поддерживает аутентификацию операционной системы.

Архитектура этого решения строится следующим образом:

  1. На клиенте создается объект HTTPСоединение, у которого параметр ИспользоватьАутентификациюОС равен Истина, а логин и пароль не заполняются.
  2. Вручную формируется XML-конверт SOAP-запроса с требуемыми параметрами операции.
  3. Запрос отправляется через метод POST с заголовками, специфичными для веб-сервисов (SOAPAction, Content-Type). В момент отправки подсистема безопасности Windows (SSPI) передает доменные учетные данные текущей рабочей станции на целевой веб-сервер.
  4. Полученный XML-ответ передается на сервер 1С, где десериализуется в объекты данных штатными средствами платформы.

Посмотрим на пример клиентской процедуры отправки SOAP-запроса:


&НаКлиенте
Процедура ВызватьСервисОтИмениПользователя()
    
    Сервер = "service.domain.local";
    Порт = 80; // Или 443 для HTTPS
    ОтносительныйАдрес = "/Services/DataExchange.asmx";
    
    // Параметры конструктора HTTPСоединение:
    // Сервер, Порт, Пользователь, Пароль, Прокси, Таймаут, ЗащищенноеСоединение, ИспользоватьАутентификациюОС
    Соединение = Новый HTTPСоединение(Сервер, Порт, "", "", , 30, , Истина);
    
    // Формируем тело SOAP-конверта вручную
    ТелоSOAP = 
    "<?xml version=""1.0"" encoding=""utf-8""?>
    |<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
    |               xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" 
    |               xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
    |  <soap:Body>
    |    <LoadData xmlns=""http://tempuri.org/"">
    |      <ParamName>ПримерЗначения</ParamName>
    |    </LoadData>
    |  </soap:Body>
    |</soap:Envelope>";
    
    Запрос = Новый HTTPЗапрос(ОтносительныйАдрес);
    Запрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
    Запрос.Заголовки.Вставить("SOAPAction", "http://tempuri.org/LoadData");
    Запрос.УстановитьТелоИзСтроки(ТелоSOAP, КодировкаТекста.UTF8);
    
    Попытка
        Ответ = Соединение.ОтправитьДляОбработки(Запрос);
        
        Если Ответ.КодСостояния = 200 Тогда
            СтрокаОтветаXML = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
            ОбработатьРезультатНаСервере(СтрокаОтветаXML);
        Иначе
            Сообщить(СтрШаблон("Ошибка вызова сервиса. Код состояния: %1", Ответ.КодСостояния));
        КонецЕсли;
        
    Исключение
        ИнформацияОбОшибке = ОписаниеОшибки();
        Сообщить("Сбой при выполнении сетевого запроса: " + ИнформацияОбОшибке);
    КонецПопытки;
    
КонецПроцедуры

Рассмотрим, как обработать полученный ответ на сервере с помощью объекта ЧтениеXML:


&НаСервереБезКонтекста
Процедура ОбработатьРезультатНаСервере(Знач СтрокаОтветаXML)
    
    Чтение = Новый ЧтениеXML;
    Чтение.УстановитьСтроку(СтрокаОтветаXML);
    
    // Переходим к разбору полезной нагрузки XML
    Пока Чтение.Прочитать() Цикл
        Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.Имя = "LoadDataResult" Тогда
            Чтение.Прочитать();
            ЗначениеОтвета = Чтение.Значение;
            // Выполняем дальнейшую бизнес-логику в информационной базе
        КонецЕсли;
    КонецЦикла;
    
    Чтение.Закрыть();
    
КонецПроцедуры

Способ 2. Запуск службы сервера 1С под доменной сервисной учетной записью

Если для интеграции критично использовать именно стандартный объект WSПрокси на стороне сервера, а конкретная персона пользователя на внешнем сервисе не играет роли (достаточно общей авторизации в домене компании), проанализируем настройку серверного окружения:

  1. В Active Directory создается отдельная техническая учетная запись (например, svc_1c_server).
  2. Данной учетной записи на сервере 1С назначается локальная привилегия Вход в качестве службы (Log on as a service), а также права на каталоги баз данных, журналов регистрации и временных файлов 1С.
  3. Служба 1C:Enterprise 8.3 Server Agent переводится с локального аккаунта на созданного доменного пользователя.
  4. На стороне внешнего сервиса предоставляются необходимые права доступа для svc_1c_server.

После перезапуска службы сервера 1С создание прокси на сервере с параметром ИспользоватьАутентификациюОС = Истина начнет передавать доменные учетные данные учетной записи службы, и ошибки авторизации исчезнут.


&НаСервере
Функция ПодключитьсяКВебСервисуПодСлужебнойУчеткой()
    
    WSDL = "http://service.domain.local/Services/DataExchange.asmx?WSDL";
    URIПространстваИмен = "http://tempuri.org/";
    ИмяСервиса = "DataExchange";
    ИмяПорта = "DataExchangeSoap";
    
    // Создаем WS-определения
    Определения = Новый WSОпределения(WSDL, , , , 15);
    
    // Инициализируем WSПрокси с аутентификацией ОС службы сервера
    Прокси = Новый WSПрокси(Определения, URIПространстваИмен, ИмяСервиса, ИмяПорта, , 30, , , Истина);
    
    Возврат Прокси;
    
КонецФункции

Способ 3. Передача идентификатора пользователя в теле или заголовке запроса

Если внешний сервис разработан силами внутренней команды компании и допускает модификацию контрактов взаимодействия, рекомендуется отказаться от авторизации по Windows-сессии в пользу модели «От имени пользователя» (On-Behalf-Of). В этом случае подключение от 1С к сервису выполняется под единой сервисной учетной записью или статическим токеном доступа, а учетная запись сотрудника, инициировавшего действие, передается внутри вызова.

В коде 1С имя текущего пользователя домена можно получить платформенной функцией:

ТекущийДоменныйПользователь = ИмяПользователяОС();

Полученное значение передается входным параметром в операцию веб-сервиса, и внешний сервис фиксирует все операции именно за данным сотрудником. Это снимает зависимость от протоколов NTLM и Kerberos на стыке серверных компонентов и значительно упрощает отладку взаимодействия систем.

Особенности настройки сети и домена

При использовании проверки подлинности Windows важно учитывать следующие требования доменной инфраструктуры:

  1. Регистрация SPN (Service Principal Name). Для прозрачной работы протокола Kerberos на целевом веб-сервере в Active Directory должны быть предварительно зарегистрированы соответствующие имена SPN для учетной записи, обслуживающей пул веб-сервиса.
  2. Политики NTLM. Если Kerberos не настроен, операционная система попытается выполнить NTLM-аутентификацию. В сетях с запретом NTLM запросы будут отклоняться даже при указании верных прав доступа.
← На главную