Как в 1С отправить HTTP-запрос с авторизацией и сохранить сессию через Cookie?

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

При интеграции 1С со сторонними веб-сервисами и REST API разработчики часто сталкиваются с ситуацией, когда первый запрос на авторизацию проходит успешно, а последующие вызовы возвращают ошибку об отсутствии прав доступа, например NoAuth или код 401 Unauthorized. Разберем подробно, почему так происходит, как правильно настроить защищенное соединение и как поддержать активную веб-сессию между несколькими запросами.

Причина проблемы: принцип работы HTTPСоединение в 1С

Проанализируем архитектуру взаимодействия платформы 1С с веб-серверами. В отличие от веб-браузеров, объект платформы HTTPСоединение работает по принципу stateless (без сохранения состояния). В нем отсутствует встроенный механизм Cookie Jar (хранилище кук), который автоматически сохраняет заголовки ответа и прикрепляет их к последующим обращениям.

Многие веб-сервисы (в частности, работающие под управлением ASP.NET и IIS) построены следующим образом: метод авторизации возвращает статус подтверждения и передает в заголовке ответа Set-Cookie уникальные токены сеанса (например, ASP.NET_SessionId или пользовательские идентификаторы сессии). Если при выполнении следующего запроса эти данные не передать обратно серверу в заголовке Cookie, сервер считает клиента неавторизованным.

Вторая распространенная проблема — использование незащищенного протокола HTTP вместо HTTPS. Если сервис настроен на обязательное шифрование, сервер возвращает перенаправление (редирект), из-за чего прямой вызов завершается ошибкой или возвращает HTML-код страницы переадресации.

Шаг 1. Настройка защищенного соединения (HTTPS)

Выясним причину первой ошибки, с которой можно столкнуться при отправке запроса. Если при обращении к серверу возвращается ответ с кодом 301/302 или скрипт редиректа на защищенный протокол, необходимо явно инициализировать защищенное соединение.

Для работы по протоколу HTTPS конструктор объекта HTTPСоединение принимает параметр ЗащищенноеСоединение. Посмотрим на пример инициализации:


// Создаем защищенное соединение для работы по протоколу HTTPS
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение("web.fort-monitor.ru", 443,,,,, ЗащищенноеСоединение);

Параметр порта 443 является стандартным для защищенных соединений. Если его опустить, платформа при указании объекта ЗащищенноеСоединениеOpenSSL выберет порт по умолчанию.

Шаг 2. Выполнение запроса авторизации и извлечение заголовка Set-Cookie

Рассмотрим, как правильно отправить первый запрос, подтверждающий учетные данные, и забрать данные сессии из ответа сервера. Важно помнить, что если в строке запроса передаются спецсимволы, их необходимо корректно кодировать.

Посмотрим на пример отправки запроса на подключение:


// Формируем запрос на подключение
АдресПодключения = "/api/Api.svc/connect?login=demo&password=demo&lang=ru-ru&timezone=4";
ЗапросАвторизации = Новый HTTPЗапрос(АдресПодключения);

ОтветАвторизации = Соединение.Получить(ЗапросАвторизации);

Если ОтветАвторизации.КодСостояния = 200 Тогда
    СтрокаОтвета = ОтветАвторизации.ПолучитьТелоКакСтроку();
    // Сервер возвращает "Ok" в теле ответа
    
    // Получаем заголовки ответа
    КукиСервера = ОтветАвторизации.Заголовки.Получить("Set-Cookie");
КонецЕсли;

В свойстве ОтветАвторизации.Заголовки хранится соответствие переданных заголовков. В заголовке Set-Cookie сервер присылает строку со значениями сессионных переменных, а также директивы для браузера.

Шаг 3. Формирование корректного заголовка Cookie для последующих запросов

Разберем типичную ошибку при работе с куками. Некоторые разработчики пытаются передать во второй запрос заголовок Set-Cookie целиком или разбить его на отдельные пользовательские заголовки. Веб-сервер такой формат не примет.

В исходящем запросе должен присутствовать строго заголовок с именем Cookie, а его значение должно содержать пары вида Имя=Значение; Имя2=Значение2. Служебные параметры директивы (такие как path=/, HttpOnly, expires=...) предназначены исключительно для браузера и не должны передаваться обратно на сервер.

Посмотрим на пример формирования заголовка для рабочего запроса:


// Пример извлечения или подстановки нужных параметров сессии
// Строка из заголовка Set-Cookie содержит ASP.NET_SessionId и SGUID
СтрокаКуки = "ASP.NET_SessionId=tp2tth5sneljjovqtiez1inw; SGUID=session_id=05f10946-c6a1-4b2f-896d-c2623fb3dcf2&Culture=ru-ru&langfile=ext-lang-ru.js&msgfile=msg-lang-ru.js&login=";

// Создаем второй запрос для получения данных
АдресДанных = "/api/Api.svc/gettree?all=true";
ЗапросДанных = Новый HTTPЗапрос(АдресДанных);

// Устанавливаем заголовок Cookie для поддержания открытой сессии
ЗапросДанных.Заголовки.Вставить("Cookie", СтрокаКуки);

ОтветДанных = Соединение.Получить(ЗапросДанных);
ТекстОтвета = ОтветДанных.ПолучитьТелоКакСтроку();

Шаг 4. Безопасное экранирование параметров URL

Проанализируем еще одну частую проблему при обращении к API с фильтрацией по датам и спискам идентификаторов. В объекте HTTPЗапрос свойство АдресРесурса не выполняет автоматическое кодирование специальных символов. Если в URL присутствуют пробелы или точки с запятой (например, в датах 2014-03-07 18:00:00), сервер вернет ошибку 400 Bad Request.

Для безопасной сборки параметров используем глобальную функцию платформы КодироватьСтроку со способом кодирования СпособКодированияСтроки.КодировкаURL:


ДатаС = КодироватьСтроку("2014-03-07 18:00:00", СпособКодированияСтроки.КодировкаURL);
ДатаПо = КодироватьСтроку("2014-03-09 18:00:00", СпособКодированияСтроки.КодировкаURL);
ПараметрыОтчета = КодироватьСтроку("duration;dist;run_time", СпособКодированияСтроки.КодировкаURL);

АдресРесурса = СтрШаблон("/api/Api.svc/getobjectsreport?date_from=%1&date_to=%2¶m=%3", ДатаС, ДатаПо, ПараметрыОтчета);
ЗапросОтчета = Новый HTTPЗапрос(АдресРесурса);
ЗапросОтчета.Заголовки.Вставить("Cookie", СтрокаКуки);

ОтветОтчета = Соединение.Получить(ЗапросОтчета);

Шаг 5. Чтение и десериализация ответа в формате JSON

После того как авторизация подтверждена и сервер вернул полезные данные, разберем полученную строку JSON в структуры и массивы 1С для дальнейшей обработки в учетной системе. Для этого используем объекты ЧтениеJSON и функцию ПрочитатьJSON:


ЧтениеЖСОН = Новый ЧтениеJSON();
ЧтениеЖСОН.УстановитьСтроку(ОтветДанных.ПолучитьТелоКакСтроку());

// Преобразуем JSON в массив структур
Данные = ПрочитатьJSON(ЧтениеЖСОН);
ЧтениеЖСОН.Закрыть();

Для Каждого Элемент Из Данные Цикл
    // Обработка полученных объектов
    ИмяОбъекта = Элемент.obj_name;
    Идентификатор = Элемент.oid;
КонецЦикла;

Альтернативный вариант: использование COM-объекта WinHTTP

Если решение работает под управлением операционной системы Windows и ручной разбор заголовков кук вызывает сложности, рассмотрим альтернативный вариант через системный компонент WinHttp.WinHttpRequest.5.1.

Преимущество этого метода заключается в том, что системная библиотека Windows автоматически сохраняет сессионные куки между последовательными вызовами одного экземпляра объекта:


Попытка
    WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
    
    // 1. Авторизация
    URLАвторизации = "https://web.fort-monitor.ru/api/Api.svc/connect?login=demo&password=demo&lang=ru-ru&timezone=4";
    WinHttp.Open("GET", URLАвторизации, Ложь);
    WinHttp.Send();
    
    // 2. Получение данных - куки передаются автоматически в рамках одного экземпляра WinHttp
    URLДанных = "https://web.fort-monitor.ru/api/Api.svc/gettree?all=true";
    WinHttp.Open("GET", URLДанных, Ложь);
    WinHttp.Send();
    
    Результат = WinHttp.ResponseText;
Исключение
    ВызватьИсключение "Ошибка выполнения запроса через WinHttp: " + ОписаниеОшибки();
КонецПопытки;

Важное примечание: при работе в клиент-серверном варианте на серверах под управлением Linux использование COM-объектов невозможно. Поэтому в кроссплатформенных решениях всегда следует отдавать предпочтение штатному объекту HTTPСоединение с ручной передачей заголовка Cookie.

Рекомендации по поддержанию сессии в фоновых заданиях

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

  1. Контроль времени жизни сессии: сессии на стороне веб-серверов имеют ограниченный срок действия (обычно от 15 до 30 минут бездействия). Не сохраняйте строку Cookie в константах или справочниках на длительный срок.
  2. Автоматический повтор авторизации: если рабочий запрос вернул статус 401 или тело ответа содержит NoAuth, алгоритм должен повторно вызвать метод подключения, обновить значение куки и повторить запрос за данными.
← На главную