При работе в старых версиях платформы (например, 1С 8.1 или ранних сборках 8.3 на обычных формах) разработчики часто сталкиваются с тем, что штатный объект HTTPСоединение некорректно обрабатывает современные протоколы безопасности HTTPS. Это приводит к получению пустых ответов или ошибкам соединения. В такой ситуации на помощь приходит системный COM-объект WinHttp.WinHttpRequest.5.1. В этой статье мы подробно разберем, как настроить авторизацию, обойти проблемы с сертификатами и заставить 1С успешно обмениваться данными с современными сайтами.
Основная причина кроется в том, что платформа 8.1 разрабатывалась в эпоху, когда стандарты безопасности были иными. Современные веб-серверы требуют использования протоколов TLS 1.2 или TLS 1.3, в то время как старые компоненты Windows и 1С по умолчанию пытаются использовать SSL 3.0 или TLS 1.0. Кроме того, механизм работы с сертификатами в 8.1 требует их обязательной прописки в файл cacert.pem, что не всегда гарантирует успех. Использование WinHttp.WinHttpRequest.5.1 позволяет делегировать работу с сетевым уровнем операционной системе, что значительно упрощает задачу.
Метод SetCredentials предназначен для обработки стандартного «рукопожатия» (handshake). Рассмотрим, как правильно инициализировать объект и отправить POST-запрос с данными авторизации. Проанализируем пример кода, который позволяет передать логин и пароль серверу:
Процедура ВыполнитьЗапросКСерверу()
Сервер = "example.com";
Ресурс = "/api/v1/data";
// Создаем объект WinHttp
Попытка
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
Исключение
Сообщить("Не удалось создать объект WinHttp: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Устанавливаем кодировку для работы с кириллицей, если необходимо
WinHttp.Option(2, "Windows-1251");
// Открываем соединение (0 - синхронный режим, 1 - асинхронный)
WinHttp.Open("POST", "https://" + Сервер + Ресурс, 0);
// Указываем данные для авторизации (0 - для сервера, 1 - для прокси)
// Важно: этот метод часто срабатывает только ПОСЛЕ того, как сервер вернет 401 ошибку
WinHttp.SetCredentials("ВашЛогин", "ВашПароль", 0);
Попытка
WinHttp.Send("Данные запроса");
Если WinHttp.Status = 200 Тогда
Результат = WinHttp.ResponseText;
Сообщить("Данные получены успешно!");
Иначе
Сообщить("Ошибка сервера. Статус: " + WinHttp.Status + " " + WinHttp.StatusText);
КонецЕсли;
Исключение
Сообщить("Ошибка при отправке запроса: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Иногда метод SetCredentials не срабатывает из-за особенностей настройки веб-сервера (если он не отправляет заголовок WWW-Authenticate). В этом случае мы можем принудительно передать данные авторизации в заголовке запроса. Для этого нам нужно закодировать строку «Логин:Пароль» в формат Base64.
Выясним причину, почему в 1С 8.1 это сделать сложнее: встроенной функции Base64Строка для обычных строк там нет. Приходится использовать временные файлы или дополнительные COM-объекты.
Функция ПолучитьЗаголовокАвторизации(Логин, Пароль)
СтрокаАвторизации = СокрЛП(Логин) + ":" + СокрЛП(Пароль);
// В 8.1 приходится использовать обходной путь через временный файл
ИмяФайла = ПолучитьИмяВременногоФайла();
ТекстДок = Новый ТекстовыйДокумент;
ТекстДок.ДобавитьСтроку(СтрокаАвторизации);
// Важно: серверы обычно ждут кодировку ANSI/ISO-8859-1 для Basic Auth
ТекстДок.Записать(ИмяФайла, "windows-1251");
ДвоичныеДанные = Новый ДвоичныеДанные(ИмяФайла);
РезультатBase64 = Base64Строка(ДвоичныеДанные);
// Удаляем перенос строки, который 1С может добавить в Base64
РезультатBase64 = СтрЗаменить(РезультатBase64, Символы.ПС, "");
РезультатBase64 = СтрЗаменить(РезультатBase64, Символы.ВК, "");
УдалитьФайлы(ИмяФайла);
Возврат "Basic " + РезультатBase64;
КонецФункции
Процедура СделатьЗапросРучнойАвторизации()
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("GET", "https://mysite.ru/info", 0);
Заголовок = ПолучитьЗаголовокАвторизации("admin", "p@ssword");
WinHttp.SetRequestHeader("Authorization", Заголовок);
WinHttp.Send();
Сообщить(WinHttp.ResponseText);
КонецПроцедуры
Проанализируем ситуацию: вы написали код, логин и пароль верны, но запрос обрывается с ошибкой «The connection with the server was terminated abnormally». Это верный признак проблем с протоколом TLS. Посмотрим, как принудительно включить поддержку TLS 1.2 через свойства объекта Option.
Существует параметр Option(9) (SecureProtocols). По умолчанию он может быть настроен на старые протоколы. Чтобы включить поддержку TLS 1.2, используем значение 2048. Если нужно поддерживать и TLS 1.1, и TLS 1.2, можно установить значение 2560.
Также разберем ситуацию с сертификатами. Если сервер использует самоподписанный сертификат, WinHttp заблокирует запрос. Чтобы проигнорировать ошибки проверки (истекший срок, неверное имя узла), используем Option(4):
// 2048 - принудительный TLS 1.2
WinHttp.Option(9, 2048);
// 13056 - сумма флагов для игнорирования всех ошибок сертификатов SSL
// (Unknown CA, Invalid CN, Expired, etc.)
WinHttp.Option(4, 13056);
SetTimeouts(Resolve, Connect, Send, Receive). Время указывается в миллисекундах.ResponseText. Это повредит данные. Используйте WinHttp.ResponseBody для получения массива байтов.WinHttp может не увидеть его автоматически. В этом случае используйте метод SetProxy(2, "ip:порт").Таким образом, мы видим, что даже в условиях ограничений платформы 1С 8.1 можно успешно работать с современными веб-сервисами. Главное — правильно настроить параметры безопасности WinHttp и корректно передать заголовки авторизации.