При интеграции 1С со сторонними веб-сервисами разработчики нередко сталкиваются с ситуацией, когда запрос через браузер или Postman проходит без нареканий и возвращает статус 200 OK, а в коде 1С вызов метода завершается критическим исключением: «Ошибка работы с Интернет: Не могу установить соединение [ОшибкаСети]».
Разберем подробнее, почему так происходит, какие параметры конструктора HTTPСоединение были пропущены или указаны некорректно, и как правильно отправлять защищенные HTTPS-запросы во встроенном языке 1С:Предприятия.
Посмотрим на исходный код, вызвавший сбой при попытке обращения по адресу https://193.233.1.1/deal_update_in:
Соединение = Новый HTTPСоединение("193.233.1.1", , , , , , Ложь, Ложь);
Запрос = Новый HTTPЗапрос("/deal_update_in");
Ответ = Соединение.Получить(Запрос);
Выясним причину ошибки сети. В данном фрагменте допущены сразу две принципиальные неточности:
HTTPСоединение второй параметр (порт) оставлен пустым, платформа по умолчанию пытается подключиться по протоколу HTTP к порту 80. Однако целевой сервис ожидает защищенное соединение HTTPS, которое стандартно работает на порту 443.ЗащищенноеСоединениеOpenSSL. В устаревших версиях платформы использовался булев флаг, однако передача значения Ложь явно запрещает использование шифрования. В результате платформа пытается передать открытый HTTP-трафик на порт или сервис, ожидающий инициализацию TLS-рукопожатия.Почему же в Postman запрос выполнялся успешно? В Postman и современных браузерах схема протокола https:// автоматически перенаправляет запрос на порт 443 и включает шифрование. Кроме того, в Postman по умолчанию часто отключена валидация сертификатов безопасности (опция SSL certificate verification: OFF), что позволяет успешно выполнять запросы напрямую к IP-адресу.
Рассмотрим по шагам, как исправить инициализацию соединения. Нам требуется явно указать порт 443 и передать экземпляр объекта ЗащищенноеСоединениеOpenSSL в соответствующий параметр конструктора.
// Инициализируем защищенное соединение по умолчанию
ЗащитаSSL = Новый ЗащищенноеСоединениеOpenSSL();
// Указываем адрес сервера, порт 443, таймаут и защищенное соединение
Соединение = Новый HTTPСоединение("193.233.1.1", 443, , , , 30, ЗащитаSSL);
Запрос = Новый HTTPЗапрос("/deal_update_in");
Попытка
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Успешный ответ: " + Ответ.ПолучитьТелоКакСтроку());
Иначе
Сообщить("Ошибка сервера: " + Строка(Ответ.КодСостояния));
КонецЕсли;
Исключение
Сообщить("Ошибка при отправке запроса: " + ОписаниеОшибки());
КонецПопытки;
Когда мы создаем Новый ЗащищенноеСоединениеOpenSSL() без передачи параметров удостоверяющих центров, платформа не выполняет строгую проверку цепочки доверия и соответствия доменного имени. Это особенно актуально, когда запрос отправляется напрямую по IP-адресу, так как большинство SSL-сертификатов выпускаются на доменное имя (FQDN), а не на числовой адрес.
Если корпоративные требования безопасности требуют валидации сервера, к которому происходит обращение, самоподписанный сертификат или цепочка удостоверяющего центра могут быть проверены явно. Разберем пример передачи локального сертификата:
// Путь к файлу сертификата сервера или доверенного УЦ
ПутьКСерт = "C:\certs\server.crt";
СертификатыУЦ = Новый СертификатыУдостоверяющихЦентров(ПутьКСерт);
// Инициализируем защищенное соединение со строгой проверкой
ЗащитаSSL = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, СертификатыУЦ);
Соединение = Новый HTTPСоединение("193.233.1.1", 443, , , , 30, ЗащитаSSL);
Запрос = Новый HTTPЗапрос("/deal_update_in");
Ответ = Соединение.Получить(Запрос);
Проанализируем еще одну частую причину ошибки «Не могу установить соединение», когда код выполняется на стороне сервера (директива &НаСервере). Служба кластера 1С (пользователь usr1cv8) может не иметь прямого выхода во внешнюю сеть или требовать прохождения через корпоративный прокси-сервер.
В таких случаях необходимо явно инициализировать объект ИнтернетПрокси:
// Использование системных настроек прокси сервера ОС
Прокси = Новый ИнтернетПрокси(Истина);
ЗащитаSSL = Новый ЗащищенноеСоединениеOpenSSL();
Соединение = Новый HTTPСоединение("193.233.1.1", 443, , , Прокси, 30, ЗащитаSSL);
Запрос = Новый HTTPЗапрос("/deal_update_in");
Ответ = Соединение.Получить(Запрос);
Если в конфигурации используется «Библиотека стандартных подсистем» (БСП), рекомендуется применять стандартизированную функцию общего модуля ПолучениеФайловИзИнтернетаКлиентСервер.НовоеЗащищенноеСоединениеOpenSSL(), которая автоматически считывает общесистемные параметры прокси и доверенные сертификаты, заданные администратором информационной базы.
Посмотрим на альтернативный способ решения проблемы. Если операционная система или используемая сборка платформы 1С не поддерживают требуемые удаленным сервером наборы шифров TLS, либо возникают непреодолимые ошибки при валидации самоподписанного сертификата на IP-адресе, в среде Windows можно задействовать системный компонент WinHttp.WinHttpRequest.5.1:
HTTP = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
HTTP.Open("GET", "https://193.233.1.1/deal_update_in", Ложь);
// Флаг 13056 отключает проверку всех ошибок SSL-сертификата (включая несовпадение имени узла)
HTTP.Option(4, 13056);
HTTP.Send();
Если HTTP.Status = 200 Тогда
Сообщить("Успешный ответ: " + HTTP.ResponseText);
Иначе
Сообщить("Ошибка: " + Строка(HTTP.Status) + " " + HTTP.StatusText);
КонецЕсли;
Таким образом, для устранения сетевой ошибки при выполнении HTTPS-запросов достаточно убедиться, что обращение идет к порту 443, а в конструктор HTTPСоединение передан корректно настроенный объект ЗащищенноеСоединениеOpenSSL.