При интеграции 1С со сторонними корпоративными системами, работающими под управлением Microsoft IIS или SharePoint, разработчики часто сталкиваются с ошибкой 401 Unauthorized (Не авторизован). Попытка передать логин и пароль в формате домен\пользователь или user@domain через стандартные свойства Пользователь и Пароль объекта WSПрокси завершается неудачей.
Проанализируем природу этой проблемы, выясним, почему обычная Basic-аутентификация не срабатывает с доменными службами, и разберем способы корректного вызова SOAP-методов с использованием встроенных механизмов платформы 1С.
Разберем, как происходит проверка прав при обращении к сервисам на базе веб-сервера IIS. Веб-сервер выполняет первичную проверку подлинности запроса. Если служба настроена на использование интегрированной проверки подлинности Windows (Integrated Windows Authentication — протоколы NTLM или Negotiate/Kerberos), она отклоняет стандартные заголовки Authorization: Basic.
Свойства Пользователь и Пароль объекта WSПрокси по умолчанию формируют именно Basic-аутентификацию. В этом случае имя и пароль кодируются по алгоритму Base64 и передаются в открытом виде, что не удовлетворяет требованиям безопасности Windows-домена.
Начиная с версии платформы 8.3.8, метод СоздатьWSПрокси объекта WSСсылкаМенеджер содержит специальный параметр, позволяющий включить аутентификацию средствами операционной системы (NTLM или Negotiate).
Синтаксис метода выглядит следующим образом:
СоздатьWSПрокси(<URIПространстваИменСервиса>, <ИмяСервиса>, <ИмяПорта>, <ИнтернетПрокси>, <Таймаут>, <ЗащищенноеСоединение>, <Местоположение>, <ИспользоватьАутентификациюОС>)
Рассмотрим пример кода для подключения к веб-сервису SharePoint:
URI = "http://schemas.microsoft.com/sharepoint/soap/";
// Передаем восьмым параметром значение Истина
Прокси = WSСсылки.WSСсылка1.СоздатьWSПрокси(
URI,
"Lists",
"ListsSoap12",
,
60,
,
,
Истина
);
ТипWSПараметра = Прокси.ФабрикаXDTO.Пакеты.Получить(URI).Получить("GetListCollection");
WSПараметр = Прокси.ФабрикаXDTO.Создать(ТипWSПараметра);
Результат = Прокси.GetListCollection(WSПараметр);
При использовании этого флага действуют важные архитектурные особенности:
Пользователь и Пароль вручную не требуется.USR1CV8). Для успешного выполнения запроса необходимо выдать этой сервисной учетной записи права доступа в целевой системе (SharePoint/IIS) и домене Active Directory.Если необходимо выполнить подключение от имени конкретного доменного пользователя, отличного от текущей учетной записи процесса операционной системы, стандартный WSПрокси не позволит передать сторонние доменные учетные данные для NTLM. В такой ситуации мы можем использовать объект HTTPСоединение и отправить сформированный вручную SOAP-конверт.
Рассмотрим по шагам реализацию такого запроса:
Сервер = "sharepoint.domain.local";
Ресурс = "/_vti_bin/Lists.asmx";
// В конструкторе HTTPСоединения передаем доменного пользователя, пароль и флаг аутентификации ОС
Соединение = Новый HTTPСоединение(
Сервер,
,
"DOMAIN\User",
"SecretPassword",
,
60,
,
Истина // ИспользоватьАутентификациюОС
);
ТелоЗапроса =
"<?xml version=""1.0"" encoding=""utf-8""?>" +
"<soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope"">" +
" <soap12:Body>" +
" <GetListCollection xmlns=""http://schemas.microsoft.com/sharepoint/soap/"" />" +
" </soap12:Body>" +
"</soap12:Envelope>";
Запрос = Новый HTTPЗапрос(Ресурс);
Запрос.Заголовки.Вставить("Content-Type", "application/soap+xml; charset=utf-8");
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
// Дальнейшая обработка ответа через ЧтениеXML или ФабрикуXDTO
КонецЕсли;
На рабочих станциях и серверах под управлением Windows для гибкой работы с NTLM и Negotiate можно применить системный COM-объект WinHttp.WinHttpRequest.5.1. Метод SetCredentials позволяет явно задать имя пользователя и пароль для аутентификации на сервере.
Посмотрим на пример работы с COM-объектом:
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("POST", "http://sharepoint.domain.local/_vti_bin/Lists.asmx", Ложь);
// Устанавливаем учетные данные для сервера (0 = HTTPREQUEST_SETCREDENTIALS_FOR_SERVER)
WinHttp.SetCredentials("DOMAIN\User", "SecretPassword", 0);
WinHttp.SetRequestHeader("Content-Type", "application/soap+xml; charset=utf-8");
ТелоXML =
"<?xml version=""1.0"" encoding=""utf-8""?>" +
"<soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope"">" +
" <soap12:Body>" +
" <GetListCollection xmlns=""http://schemas.microsoft.com/sharepoint/soap/"" />" +
" </soap12:Body>" +
"</soap12:Envelope>";
WinHttp.Send(ТелоXML);
Если WinHttp.Status = 200 Тогда
РезультатXML = WinHttp.ResponseText;
КонецЕсли;
Проанализируем сопутствующие настройки инфраструктуры, влияющие на работу NTLM и Kerberos:
ИспользоватьАутентификациюОС на сервере Linux необходимо настроить Kerberos на уровне ОС (файл /etc/krb5.conf, получение билета kinit или привязка keytab-файла).