Авторизация на сайте средствами 1С: Как обойти защиту Keycloak и настроить парсинг данных

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

При интеграции 1С с внешними веб-ресурсами разработчики часто сталкиваются с задачей автоматического сбора данных (парсинга) с сайтов, защищенных современными системами авторизации (SSO), такими как Keycloak или другие решения на базе протокола OpenID Connect (OIDC). Отличным примером служит портал Московской биржи (MOEX) и связанный с ним ресурс NSDData.

В этой статье мы подробно разберем, как обойти программные ограничения встроенных механизмов 1С (особенно на старых платформах вроде 1С 8.1 или при использовании Обычных форм в 1С 8.3) и настроить надежную авторизацию без использования дорогостоящего платного API.

Почему визуальный метод (через ПолеHTMLДокумента) не подходит?

На первый взгляд самым простым решением кажется вывод формы авторизации на экран через объект ПолеHTMLДокумента, заполнение полей логина/пароля программными методами и программный "клик" по кнопке "Войти". Однако на практике этот подход быстро заходит в тупик по следующим причинам:

Поэтому мы проанализируем и внедрим гораздо более надежный способ — программную эмуляцию HTTP-запросов.

Протокол OpenID Connect (OIDC) и структура запросов Keycloak

Когда мы нажимаем кнопку "Вход" на целевом сайте, происходит перенаправление на сервер авторизации. Ссылка перенаправления содержит множество параметров:


https://sso.moex.com/auth/realms/moex/protocol/openid-connect/auth
?kc_locale=ru
&response_type=code
&redirect_uri=https%3A%2F%2Fnsddata.ru%2Fru
&client_id=NSDDATA
&nonce=62ffba1566b5c1016d388b3c74f48de2
&state=a2d366b9b88bcd2d14421b147f643dac
&scope=openid

Сервер авторизации Keycloak динамически генерирует форму входа, внедряя в нее уникальные сессионные параметры. Нам необходимо передать POST-запрос на адрес обработчика формы авторизации. Проанализируем структуру этого запроса:

Решение проблемы с помощью COM-объекта WinHttp.WinHttpRequest.5.1

Поскольку встроенный в 1С объект HTTPСоединение на старых платформах не умеет гибко управлять заголовками и автоматически сохранять куки (Cookies), мы будем использовать внешний COM-объект операционной системы Windows — WinHttp.WinHttpRequest.5.1.

Использование этого объекта решает сразу три важнейшие задачи:

  1. Автоматическое сохранение сессии: Объект хранит полученные от сервера куки (Cookies) на протяжении всего времени жизни объекта в памяти 1С. Вам не придется вручную парсить заголовки Set-Cookie.
  2. Поддержка современных протоколов шифрования: Через настройки объекта можно принудительно включить поддержку TLS 1.2 и TLS 1.3, что критически важно для работы с современными веб-ресурсами.
  3. Управление редиректами: Мы можем контролировать автоматический переход по ссылкам перенаправления (код ответа 302).

Реализуем алгоритм авторизации по шагам

Рассмотрим пошаговый алгоритм решения нашей задачи на языке 1С.

Шаг 1. Инициализация объекта WinHttp и настройка параметров безопасности

Создаем COM-объект и устанавливаем необходимые флаги работы с защищенным соединением SSL/TLS.


WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// Включаем поддержку TLS 1.2 (флаг 2048)
WinHttp.Option(9, 2048); 
// Отключаем автоматический редирект, чтобы вручную перехватить код авторизации
WinHttp.Option(6, 0); 

Шаг 2. Выполнение первичного GET-запроса для получения CSRF-токена и параметров сессии

Нам необходимо зайти на страницу авторизации, чтобы сервер выдал нам куки сессии и сгенерировал форму с уникальными токенами безопасности.


АдресАвторизации = "https://sso.moex.com/auth/realms/moex/protocol/openid-connect/auth?kc_locale=ru&response_type=code&redirect_uri=https%3A%2F%2Fnsddata.ru%2Fru&client_id=NSDDATA&scope=openid";

WinHttp.Open("GET", АдресАвторизации, Ложь);
WinHttp.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
WinHttp.Send();

Если WinHttp.Status <> 200 Тогда
    ВызватьИсключение "Не удалось получить первичную страницу авторизации. Код ошибки: " + WinHttp.Status;
КонецЕсли;

ТекстОтвета = WinHttp.ResponseText;

Шаг 3. Парсинг динамических параметров из HTML-кода страницы

Теперь из полученного текста страницы нам нужно вытащить адрес действия формы (атрибут action тега form) и значение скрытого поля CSRF. Для этого напишем простую вспомогательную функцию поиска подстроки или воспользуемся регулярными выражениями.


// Функция для поиска параметров между двумя тегами/строками
Функция ПолучитьПараметрМеждуСтрок(ТекстИсточник, ЛеваяГраница, ПраваяГраница)
    ПозЛевая = Найти(ТекстИсточник, ЛеваяГраница);
    Если ПозЛевая = 0 Тогда
        Возврат "";
    КонецЕсли;
    НачалоПоиска = ПозЛевая + СтрДлина(ЛеваяГраница);
    ПозПравая = Найти(Сред(ТекстИсточник, НачалоПоиска), ПраваяГраница);
    Если ПозПравая = 0 Тогда
        Возврат "";
    КонецЕсли;
    Возврат Сред(ТекстИсточник, НачалоПоиска, ПозПравая - 1);
КонецФункции

Используя эту функцию, извлекаем динамические параметры из полученного HTML-кода:


// Извлекаем action формы (целевой URL для POST запроса)
АдресОбработчикаФормы = ПолучитьПараметрМеждуСтрок(ТекстОтвета, "id=""kc-form-login"" action=""", """");
// Извлекаем CSRF токен
ТокенCSRF = ПолучитьПараметрМеждуСтрок(ТекстОтвета, "name=""CSRF"" value=""", """");

Если ПустаяСтрока(АдресОбработчикаФормы) Или ПустаяСтрока(ТокенCSRF) Тогда
    ВызватьИсключение "Не удалось распарсить защитные токены со страницы входа.";
КонецЕсли;

Шаг 4. Отправка POST-запроса с логином и паролем

Теперь мы готовы отправить данные авторизации на сервер. Формируем тело запроса. Обратите внимание, что значения параметров обязательно должны быть закодированы в формате URL (все спецсимволы, пробелы и кириллица должны заменяться на их шестнадцатеричные коды).


// Для простоты примера предполагаем, что логин и пароль содержат только латиницу и цифры
ТелоЗапроса = "username=" + Логин + "&password=" + Пароль + "&CSRF=" + КодироватьСтроку(ТокенCSRF, СпособКодированияСтроки.КодироватьИменаКомпьютеров) + "&login=Войти";

WinHttp.Open("POST", АдресОбработчикаФормы, Ложь);
WinHttp.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
WinHttp.SetRequestHeader("User-Agent", "Mozilla/5.0");
WinHttp.Send(ТелоЗапроса);

Шаг 5. Обработка редиректа и переход на целевой сайт

Поскольку при успешной авторизации сервер Keycloak возвращает статус перенаправления 302 Found, нам необходимо прочесть заголовок Location, в котором будет содержаться ссылка с кодом авторизации, ведущая обратно на наш целевой сайт nsddata.ru.


Если WinHttp.Status = 302 Тогда
    // Получаем адрес перенаправления, содержащий временный авторизационный код (code)
    АдресПерехода = WinHttp.GetResponseHeader("Location");
    
    // Переходим по этой ссылке, чтобы целевой сайт зафиксировал успешный вход и выдал свои рабочие сессионные куки
    WinHttp.Open("GET", АдресПерехода, Ложь);
    WinHttp.Send();
    
    Если WinHttp.Status = 200 Тогда
        Сообщить("Авторизация успешно завершена! Сессия активна.");
    Иначе
        Сообщить("Не удалось подтвердить сессию на целевом сайте. Код ошибки: " + WinHttp.Status);
    КонецЕсли;
Иначе
    Сообщить("Авторизация отклонена сервером. Проверьте логин и пароль. Код ошибки: " + WinHttp.Status);
КонецЕсли;

Дальнейшая работа с данными сайта

После успешного прохождения шага 5 наш COM-объект WinHttp хранит в своей памяти все куки авторизованного сеанса. Теперь мы можем выполнять любые GET и POST-запросы к страницам сайта nsddata.ru для парсинга таблиц, скачивания файлов отчетов или получения JSON-данных.

Пример получения защищенной страницы после авторизации:


АдресДанных = "https://nsddata.ru/ru/personal/cabinet/some_data_page";
WinHttp.Open("GET", АдресДанных, Ложь);
WinHttp.Send();

Если WinHttp.Status = 200 Тогда
    // Полученный HTML-код страницы теперь можно обрабатывать парсером в 1С
    КодСтраницыДанных = WinHttp.ResponseText;
КонецЕсли;

Таким образом, мы полностью автоматизировали процесс авторизации через современную систему Keycloak на платформе 1С без использования сторонних платных сервисов и без необходимости открывать интерактивные формы входа для пользователя.

← На главную