При интеграции решений на платформе 1С с корпоративными микросервисами разработчики часто сталкиваются с необходимостью настройки сквозной доменной авторизации (Single Sign-On, SSO). Типичная ситуация: при обращении к веб-сервису через обычный браузер всё работает отлично, но как только мы пытаемся выполнить аналогичный запрос из кода 1С с помощью встроенного объекта HTTPСоединение, сервер возвращает ошибку 401 Unauthorized.
В этой статье мы подробно разберем, почему возникает данная проблема, как работает механизм Negotiate-рукопожатия под капотом операционной системы и какими способами можно решить эту задачу в 1С.
Проанализируем поведение системы. Протокол Negotiate (использующий Kerberos или NTLM) требует многоэтапного обмена сообщениями между клиентом и сервером в рамках одной TCP-сессии:
401 Unauthorized и присылает заголовок WWW-Authenticate: Negotiate.Authorization: Negotiate [билет_в_кодировке_base64].200 OK.Если в 1С у объекта HTTPСоединение свойство ИспользоватьАутентификациюОС установлено в значение Истина, платформа должна автоматически выполнить эти шаги. Однако на практике этого часто не происходит из-за системных политик безопасности Windows.
Выясним причину: системная библиотека Windows (WinHTTP), которую использует платформа 1С, автоматически передает доменные учетные данные пользователя только для узлов, входящих в зону «Локальная интрасеть» (Local Intranet). Если имя хоста микросервиса не относится к этой зоне (например, используется полное доменное имя FQDN вроде service.domain.local), Windows блокирует генерацию тикета Kerberos из соображений безопасности. В результате 1С не может ответить на вызов сервера и возвращает ошибку 401.
Ниже мы рассмотрим три способа решения этой проблемы.
Если код выполняется в операционной системе Windows, самым простым и надежным способом обойти ограничения безопасности групповых политик является использование COM-объекта WinHttp.WinHttpRequest.5.1.
Ключевым преимуществом этого метода является возможность принудительно переопределить политику автоматического входа с помощью метода SetAutoLogonPolicy(0). Значение 0 (соответствует системной константе AutoLogonPolicy_Always) заставляет систему отправлять доменные учетные данные на любой узел, независимо от того, к какой зоне безопасности он принадлежит.
Разберем пример реализации этого механизма на языке 1С:
АдресСервиса = "http://ИмяХоста/authentication-microservice/auth";
Попытка
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// Устанавливаем политику авторизации: всегда отправлять учетные данные ОС
WinHttp.SetAutoLogonPolicy(0);
// Инициализируем GET-запрос (Ложь указывает на синхронный режим работы)
WinHttp.Open("GET", АдресСервиса, Ложь);
// Отправляем запрос серверу
WinHttp.Send();
// Получаем результат работы сервиса
КодСтатуса = WinHttp.Status;
Если КодСтатуса = 200 Тогда
РезультатJSON = WinHttp.ResponseText;
// Дальнейшая обработка полученного JSON-пакета
Сообщить("Авторизация успешна. Ответ сервера: " + РезультатJSON);
Иначе
ВызватьИсключение "Сервер вернул код ответа: " + КодСтатуса;
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("Интеграция.АутентификацияОС",
УровеньЖурналаРегистрации.Ошибка,,,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Ошибка при выполнении HTTP-запроса через WinHttp!";
КонецПопытки;
Важное ограничение: Данный способ жестко привязан к среде Windows и технологии COM. Он не будет работать, если сервер 1С функционирует под управлением операционной системы Linux.
Если мы хотим использовать стандартные механизмы 1С и объект HTTPСоединение, нам потребуется скорректировать настройки безопасности Windows на компьютере, с которого выполняется запрос. Это позволит штатным механизмам платформы без проблем получать Kerberos-билеты.
Выполним следующие шаги для настройки:
http://ИмяХоста или маску вида *.domain.local) в список разрешенных узлов.После применения этих настроек операционная система распознает узел как безопасный интрасетевой ресурс и разрешит платформе 1С генерировать Kerberos-токены. Код в 1С при этом будет выглядеть стандартно:
// Создаем защищенное соединение, если сервис работает по HTTPS
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
// Инициализируем HTTP-соединение с включенным флагом аутентификации ОС
Соединение = Новый HTTPСоединение(
"ИмяХоста",,,,, // Порт, Прокси-сервер и таймауты
,, // ИмяПользователя и Пароль не указываем для SSO
ЗащищенноеСоединение,
Истина // ИспользоватьАутентификациюОС = Истина
);
Запрос = Новый HTTPЗапрос("/authentication-microservice/auth");
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Успешное подключение средствами платформы 1С!");
Иначе
Сообщить("Ошибка авторизации. Код состояния: " + Ответ.КодСостояния);
КонецЕсли;
В тех случаях, когда изменить настройки зон безопасности Windows не представляется возможным (например, из-за жестких ограничений доменных политик), платформа 1С позволяет пойти другим путем. Мы можем явно передать имя и пароль доменного пользователя в параметры конструктора HTTPСоединение.
При этом важно соблюдать правильный формат указания имени пользователя. Платформа поддерживает два варианта:
ИМЯ_ДОМЕНА\ИмяПользователяИмяПользователя@domain.localРассмотрим пример кода:
ИмяПользователя = "CORP\service_1c";
ПарольПользователя = "MySecureDomainPassword123";
// Передаем параметры доменной учетной записи непосредственно в соединение
Соединение = Новый HTTPСоединение(
"ИмяХоста",,,,
Прокси,
ИмяПользователя,
ПарольПользователя,,
Истина // Включаем аутентификацию ОС
);
Запрос = Новый HTTPЗапрос("/authentication-microservice/auth");
Ответ = Соединение.Получить(Запрос);
При таком подходе платформа 1С самостоятельно выполнит доменную авторизацию на основе предоставленных данных, минуя автоматические системные запреты для зон безопасности.
Отдельно разберем крайне важный нюанс, связанный с контекстом выполнения кода в 1С. Очень часто разработчики сталкиваются с тем, что доменная авторизация отлично отрабатывает на стороне клиента (в режиме «Тонкий клиент» под учетной записью текущего пользователя Windows), но полностью ломается с ошибкой 401 при переносе этого кода на сервер (например, при регламентных заданиях или вызовах в привилегированных модулях).
Выясним причину этой проблемы. По умолчанию служба «Агент сервера 1С:Предприятия» (процессы rphost.exe) запускается под локальной системной учетной записью (например, .\usr1cv8 или NetworkService). Локальный пользователь операционной системы не имеет контекста в домене Active Directory и физически не может получить Kerberos-тикет для авторизации во внешней системе.
Чтобы решить эту проблему, выполните следующие действия:
DOMAIN\usr1cv8-server).Только при соблюдении этих условий серверный код 1С сможет прозрачно и безопасно проходить сквозную авторизацию по протоколу Negotiate.