При интеграции систем «1С:Предприятие» со сторонними веб-службами разработчики регулярно сталкиваются со сложными инфраструктурными и протокольными ошибками. Наиболее популярными среди них являются некорректная обработка SOAP-заголовков принимающей стороной и невозможность перехватить защищенный трафик для анализа. Разберем по шагам, как решить проблему несовпадения SOAP Action и как правильно подружить платформу 1С с прокси-анализатором Fiddler для расшифровки HTTPS-трафика.
Данная техническая проблема чаще всего возникает при попытке отправить запрос к веб-сервисам, развернутым на платформе WCF (Windows Communication Foundation), или использующим стандарт SOAP 1.2 совместно с механизмами адресации WS-Addressing.
Выясним глубинную причину этой ошибки. Согласно спецификации SOAP 1.2, идентификация вызываемого метода (действие или Action) может передаваться не только в HTTP-заголовках запроса, но и непосредственно внутри XML-тела (SOAP-конверта) в блоке заголовков WS-Addressing (например, в теге <wsa:Action> внутри секции <soap:Header>). Принимающий WCF-сервер ожидает полной идентичности между HTTP-заголовком и XML-заголовком.
Платформа «1С:Предприятие» при использовании встроенного объекта WSПрокси генерирует SOAP-конверт автоматически. При этом 1С нативно не поддерживает стандарты WS-Addressing, WS-Security и WS-Policy. В результате XML-тело уходит на сервер без служебных тегов адресации. Сервер WCF видит пустое значение Action внутри самого SOAP-сообщения (которое интерпретируется как пустая строка '') и заполненный Action в HTTP-заголовке. Возникает конфликт сопоставления, и сервер возвращает ошибку.
Рассмотрим подробнее три основных способа решения этой проблемы.
Если вызываемый сторонний веб-сервис жестко требует наличия WS-Addressing, стандартный механизм WSПрокси применить не удастся. Единственным надежным способом обойти ограничение платформы является отправка низкоуровневого HTTP-запроса с самостоятельным формированием SOAP-конверта.
Проанализируем пример кода, в котором мы вручную конструируем XML-запрос с необходимыми пространствами имен и отправляем его через HTTPСоединение:
// Шаг 1. Определяем параметры подключения и заголовки
АдресПодключения = "example.com";
РесурсНаСервере = "/XRMServices/2011/Organization.svc";
ИмяМетода = "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/RetrieveMultiple";
Заголовки = Новый Соответствие();
// Указываем корректный Content-Type для SOAP 1.2 с параметром action
Заголовки.Вставить("Content-Type", "application/soap+xml; charset=utf-8; action=""" + ИмяМетода + """");
// Шаг 2. Формируем тело SOAP-запроса вручную
ЗаписьXML = Новый ЗаписьXML();
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("s", "Envelope", "http://www.w3.org/2003/05/soap-envelope");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("a", "http://www.w3.org/2005/08/addressing");
// Вручную формируем секцию Header с поддержкой WS-Addressing
ЗаписьXML.ЗаписатьНачалоЭлемента("s", "Header", "http://www.w3.org/2003/05/soap-envelope");
ЗаписьXML.ЗаписатьНачалоЭлемента("a", "Action", "http://www.w3.org/2005/08/addressing");
ЗаписьXML.ЗаписатьТекст(ИмяМетода);
ЗаписьXML.ЗаписатьКонецЭлемента(); // a:Action
ЗаписьXML.ЗаписатьКонецЭлемента(); // s:Header
// Формируем тело запроса s:Body
ЗаписьXML.ЗаписатьНачалоЭлемента("s", "Body", "http://www.w3.org/2003/05/soap-envelope");
// Здесь записываются параметры вашего метода
ЗаписьXML.ЗаписатьНачалоЭлемента("RetrieveMultiple", "http://schemas.microsoft.com/xrm/2011/Contracts/Services");
// Тело метода...
ЗаписьXML.ЗаписатьКонецЭлемента(); // RetrieveMultiple
ЗаписьXML.ЗаписатьКонецЭлемента(); // s:Body
ЗаписьXML.ЗаписатьКонецЭлемента(); // s:Envelope
ТекстЗапроса = ЗаписьXML.Закрыть();
// Шаг 3. Отправляем запрос через HTTP-соединение
Защита = Новый ЗащищенноеСоединениеOpenSSL();
HTTPСоединение = Новый HTTPСоединение(АдресПодключения, 443, , , , , Защита);
HTTPЗапрос = Новый HTTPЗапрос(РесурсНаСервере, Заголовки);
HTTPЗапрос.УстановитьТелоИзСтроки(ТекстЗапроса, КодировкаТекста.UTF8);
Попытка
HTTPОтвет = HTTPСоединение.ОтправитьДляАнализа(HTTPЗапрос);
РезультатСтрокой = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
// Обрабатываем полученный XML-ответ
Исключение
ВызватьИсключение "Ошибка отправки SOAP-запроса: " + ОписаниеОшибки();
КонецПопытки;
Если у вас или вашей компании есть административный доступ к настройкам и исходному коду вызываемого веб-сервиса, наиболее простым решением будет изменить конфигурацию привязки на стороне сервера.
По умолчанию конфигурация WCF часто использует привязку wsHttpBinding, которая требует шифрования и жесткой адресации. Измените привязку на **basicHttpBinding**. Данный режим работает по более простому стандарту SOAP 1.1, не требует наличия заголовков WS-Addressing в теле XML и полностью совместим со встроенным в 1С механизмом WSПрокси.
Если полный переход на basicHttpBinding невозможен, измените свойства кастомной привязки в конфигурационном файле сервера (web.config), отключив требование адресации путем установки параметра AddressingVersion.None.
Иногда платформа 1С некорректно импортирует структуру WSDL из-за наличия сложных типов связывания или нескольких объявленных портов. В результате 1С генерирует неправильные HTTP-заголовки.
Решить эту проблему можно локальным редактированием файла описания сервиса:
<soap:operation> или <soap12:operation>).soapAction заполнен корректно и содержит полный путь к методу. При необходимости измените его вручную или удалите конфликтующие элементы привязки.WSОпределения, указав путь к локально сохраненному и модифицированному файлу WSDL вместо URL-ссылки.---
Для детального анализа отправляемых запросов незаменимым инструментом является локальный прокси-сервер Fiddler. Однако при попытке пропустить трафик через него разработчики сталкиваются с системной ошибкой в 1С: «Ошибка работы с Интернет: Удаленный узел не прошел проверку». Это происходит из-за того, что Fiddler подменяет оригинальный SSL-сертификат целевого ресурса своим собственным самоподписанным сертификатом расшифровки. Платформа 1С считает этот сертификат недоверенным и обрывает соединение.
Рассмотрим, как правильно решить проблему доверия к сертификатам в зависимости от используемой платформы и режима совместимости.
Начиная с версии платформы 1С:Предприятие 8.3.8, разработчикам доступна возможность автоматического использования системных сертификатов операционной системы. Если в вашей базе отключены старые режимы совместимости (или установлен режим 8.3.8 и выше), вам достаточно один раз разрешить Fiddler установить свой корневой сертификат в доверенные центры Windows.
Однако, если ваша конфигурация запущена в режиме совместимости с более старыми версиями (например, 8.2.16), платформа по умолчанию игнорирует системное хранилище ОС. Чтобы заставить 1С использовать сертификаты Windows, необходимо явно переопределить создание защищенного соединения в коде инициализации WSПрокси:
// Явно указываем платформе использовать хранилище Windows
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(
Новый СертификатКлиентаWindows(),
Новый СертификатыУдостоверяющихЦентровWindows()
);
// Подставляем защищенное соединение в конструктор WSПрокси
WSПрокси = Новый WSПрокси(
Определения,
"http://example.com/namespace",
"ServiceName",
"PortName",
ЗащищенноеСоединение
);
После добавления этих параметров при вызове методов веб-сервиса платформа успешно подхватит корневой сертификат Fiddler из хранилища операционной системы, и весь трафик отобразится в окне отладчика без каких-либо ошибок.
Если вы вынуждены работать на старых релизах платформы (до 8.3.7 включительно) или без изменения программного кода конфигурации, единственным выходом будет ручное редактирование файла доверенных сертификатов 1С — cacert.pem, расположенного в каталоге установки платформы (по умолчанию: C:\Program Files\1cv8\имя_релиза\bin\cacert.pem).
Основная сложность заключается в том, что Fiddler экспортирует сертификат в бинарном формате DER (.cer), в то время как файл cacert.pem требует текстового кодирования Base-64 (PEM).
Разберем по шагам правильный процесс экспорта и конвертации:
certmgr.msc.fiddler.cer.certutil, выполнив команду:
certutil -encode FiddlerRoot.cer FiddlerRoot.pem
-----BEGIN CERTIFICATE----- и -----END CERTIFICATE-----.cacert.pem из каталога bin вашей версии платформы 1С, перейдите в самый конец документа и вставьте скопированный блок текста новой строкой.cacert.pem (для этого могут потребоваться права Администратора) и перезапустите сеанс «1С:Предприятия».Выполнив указанные настройки, вы сможете без труда отлаживать любые исходящие HTTP и SOAP запросы из 1С, анализировать структуру заголовков и отправляемые XML-сообщения, что позволит оперативно устранять любые ошибки интеграции со сторонними информационными системами.