При интеграции 1С с различными веб-сервисами часто возникает задача автоматической авторизации на сайте для последующего обмена данными, особенно если у сайта нет готового API. Стандартный сценарий — это отправка логина и пароля через веб-форму. Давайте подробно разберем, как воспроизвести этот процесс в коде 1С, используя HTTPЗапрос, и какие подводные камни могут встретиться на пути.
Основная проблема заключается в том, чтобы в точности повторить запрос, который отправляет браузер при нажатии на кнопку "Войти". Это включает в себя не только URL и метод запроса (POST), но и правильные заголовки, cookie для поддержания сессии и, самое главное, корректно сформированное тело запроса.
Прежде чем писать код, необходимо стать "детективом" и выяснить, что именно происходит "под капотом" браузера в момент авторизации. Это самый важный этап, от которого зависит успех всей операции.
Инструменты для анализа:
На что обращаем внимание:
/login.php, /auth и т.п.POST.Content-Type (часто это application/x-www-form-urlencoded) и Cookie (здесь передается идентификатор сессии, например, PHPSESSID).application/x-www-form-urlencoded они выглядят как строка пар "ключ=значение", соединенных амперсандом (&). Например: login=МояПочта&password=МойПароль&...Как правило, сначала нужно сделать GET-запрос на страницу входа, чтобы получить от сервера сессионный Cookie, а затем уже отправлять POST-запрос на авторизацию, передавая этот Cookie в заголовках.
Вооружившись данными из анализатора, переходим к написанию кода в 1С. Рассмотрим ключевые моменты, с которыми столкнулся автор.
Сначала подготовим все необходимые компоненты: адрес, заголовки и тело запроса.
1. Заголовки. Создаем структуру Соответствие и заполняем ее заголовками, которые мы подсмотрели в браузере. Обязательно добавляем полученный ранее Cookie.
// Предполагается, что КодСессии мы получили ранее из ответа на GET-запрос
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
Заголовки.Вставить("Cookie", "PHPSESSID=" + Объект.КодСессии);
// Можно добавить и другие заголовки для большей схожести с запросом браузера
Заголовки.Вставить("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36");
2. Тело запроса. Строку для тела запроса формируем в точности так, как она выглядела в разделе Form Data анализатора.
// Пример из обсуждения
ТекстТелаЗапроса = "login=МояПочта&password=МойПароль&from_page=http%3A%2F%2Ftickets.bolshoi.ru%2Fru%2Fticket%2F";
В обсуждении возникла главная загвоздка: как правильно передать сформированное тело в объект HTTPЗапрос. Есть два основных способа, и выбор между ними оказался критичным.
Нерабочий вариант (в данном случае): УстановитьИмяФайлаТела
Изначально была попытка записать строку с данными в текстовый файл, а затем передать этот файл в запрос.
// Вариант, который не сработал у автора
ИмяФайлаЗапроса = ПолучитьИмяВременногоФайла("txt");
ТекстовыйФайл = Новый ТекстовыйДокумент;
ТекстовыйФайл.УстановитьТекст(ТекстТелаЗапроса);
ТекстовыйФайл.Записать(ИмяФайлаЗапроса, КодировкаТекста.UTF8);
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаЗапроса); // Этот метод не дал нужного результата
Почему это могло не сработать? Вероятная причина — кодировка файла. При записи файла в кодировке UTF-8 с помощью объекта ТекстовыйДокумент, 1С может добавлять в начало файла специальный невидимый маркер последовательности байтов (BOM). Некоторые веб-серверы не ожидают этот маркер в теле запроса с Content-Type: application/x-www-form-urlencoded и не могут корректно разобрать данные, что приводит к ошибке авторизации.
Рабочий вариант: УстановитьТелоИзСтроки
Это более прямой и надежный способ для отправки текстовых данных. Он позволяет избежать промежуточных файловых операций и связанных с ними проблем.
// Правильный и работающий вариант
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
// Напрямую устанавливаем тело из строки, явно указывая кодировку
HTTPЗапрос.УстановитьТелоИзСтроки(ТекстТелаЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Отправляем запрос и получаем ответ
// Соединение = Новый HTTPСоединение("имя-сайта.ру");
// Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
// Проверяем результат
// Если КодСостояния ответа 200 или 302 (редирект), то, скорее всего, авторизация прошла успешно
// ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();
Важное уточнение: В современных версиях платформы 1С у метода УстановитьТелоИзСтроки появился третий параметр ИспользованиеByteOrderMark. Явное указание ИспользованиеByteOrderMark.НеИспользовать позволяет гарантированно избежать проблемы с BOM.
Соберем все шаги в единый алгоритм для успешной авторизации:
PHPSESSID)."ключ1=значение1&ключ2=значение2...".HTTPЗапрос, передав в него адрес ресурса для авторизации и подготовленные заголовки.HTTPЗапрос.УстановитьТелоИзСтроки() для добавления тела запроса.После успешной авторизации вы сможете выполнять другие запросы к защищенным страницам сайта, не забывая передавать тот же самый сессионный Cookie в заголовках каждого запроса.