Перейти к основному содержимому

7.05. Справочник по SOAP

Разработчику Архитектору Инженеру

Справочник по SOAP

1. Общая структура SOAP-сообщения

SOAP-сообщение — это XML-документ с фиксированной структурой, определяемой схемами http://schemas.xmlsoap.org/soap/envelope/ (SOAP 1.1) или http://www.w3.org/2003/05/soap-envelope (SOAP 1.2).

<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<soap:Header> <!-- Необязательный -->
<!-- Заголовки SOAP -->
</soap:Header>

<soap:Body> <!-- Обязательный -->
<!-- Тело сообщения: вызов операции, ответ или Fault -->
</soap:Body>

</soap:Envelope>

Валидация: Всё содержимое <soap:Body> и <soap:Header> должно быть в пространствах имён, отличных от http://schemas.xmlsoap.org/soap/envelope/, иначе нарушается спецификация (см. Section 4, SOAP 1.1; Section 2.6, SOAP 1.2).


2. Элемент <soap:Envelope>

Атрибуты:

АтрибутОбязательностьЗначение по умолчаниюОписание
encodingStyle❌ (устаревший)Указывает правила сериализации данных (например, http://schemas.xmlsoap.org/soap/encoding/). Устарел в SOAP 1.2. Не рекомендуется: большинство реализаций используют XML Schema (XSD)-описания типов, а не soap:encoding.
mustUnderstand❌ (нельзя)Запрещён на <Envelope>. Разрешён только на элементах внутри <Header>.
role / actor❌ (нельзя)Атрибут actor (SOAP 1.1) / role (SOAP 1.2) недопустим на <Envelope>.

🔹 encodingStyle в SOAP 1.2 — не определён (введён в SOAP 1.1, но признан избыточным; в 1.2 удалён, хотя в схеме может присутствовать как расширяемый атрибут *).


3. Элемент <soap:Header>

Опциональный. Содержит заголовки — метаданные, модифицирующие поведение обработки сообщения (аутентификация, маршрутизация, транзакции и т.п.).

Структура подзаголовка:

<ns:Security xmlns:ns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
soap:mustUnderstand="1"
soap:role="http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver">
<!-- Содержимое заголовка -->
</ns:Security>

Атрибуты подзаголовка (на каждом дочернем элементе <Header>):

АтрибутПрименимостьВозможные значенияОписание
soap:mustUnderstand✅ Обязателен при необходимости"0" | "1" | "false" | "true"Указывает, должен ли получатель (с заданной role) понимать и обработать заголовок. При 1/true и невозможности обработки — возвращается soap:MustUnderstand Fault.
soap:actor✅ Только SOAP 1.1URIОпределяет, кому адресован заголовок среди цепочки получателей (intermediaries). Устаревшее в SOAP 1.2.
soap:role✅ Только SOAP 1.2Один из URI: • http://www.w3.org/2003/05/soap-envelope/role/nonehttp://www.w3.org/2003/05/soap-envelope/role/ultimateReceiverhttp://www.w3.org/2003/05/soap-envelope/role/next • произвольный URI (для intermediaries)Замена actor. Определяет роль получателя. Все заголовки без role по умолчанию → ultimateReceiver.
soap:relay✅ Только SOAP 1.2"0" | "1" | "false" | "true"Если 1, промежуточный узел, не распознающий заголовок, должен передать его дальше. Игнорируется при mustUnderstand="1". По умолчанию — 0.

Проверка обработки:

  • Получатель с определённой role обязан обработать все заголовки, адресованные ему (role совпадает или отсутствует и роль — ultimateReceiver).
  • При mustUnderstand="1" и отсутствии обработчика — ошибка, даже если relay="1".

4. Элемент <soap:Body>

Обязателен. Содержит тело запроса/ответа либо soap:Fault.

Возможные дочерние элементы:

ТипОписание
RPC-стиль (устаревший)<methodName> с параметрами как дочерними элементами. Требует encodingStyle. Не рекомендуется.
Document/Literal (современный)Элемент с именем операции (например, <GetUserRequest>) или <xsd:element> из WSDL. Содержимое строго типизировано XSD-схемой.
<soap:Fault>Стандартный элемент ошибки. Единственный допустимый дочерний элемент в случае ответа с ошибкой.

🔹 В одном <Body> допускается только один корневой элемент (кроме Fault — он единственный).


5. Элемент <soap:Fault> (ошибки)

Стандартный механизм сообщений об ошибках. Обязательный в SOAP 1.1 и 1.2. Размещается только внутри <Body>, единственный дочерний элемент.

Структура SOAP 1.1:

<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring xml:lang="en">Invalid request</faultstring>
<faultactor>http://example.com/intermediary</faultactor> <!-- ❌ в SOAP 1.2 -->
<detail>
<ns:ValidationError xmlns:ns="...">
<code>USR_001</code>
<message>UserID is required</message>
</ns:ValidationError>
</detail>
</soap:Fault>

Структура SOAP 1.2:

<soap:Fault xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
<soap:Subcode>
<soap:Value>ns:InvalidFormat</soap:Value>
</soap:Subcode>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Invalid XML format</soap:Text>
<soap:Text xml:lang="ru">Неверный формат XML</soap:Text>
</soap:Reason>
<soap:Node>http://example.com/node2</soap:Node> <!-- ✅ аналог faultactor -->
<soap:Role>http://www.w3.org/2003/05/soap-envelope/role/next</soap:Role>
<soap:Detail>
<ns:AppError xmlns:ns="...">
<code>XSD-101</code>
</ns:AppError>
</soap:Detail>
</soap:Fault>

🔹 Поля faultcode (SOAP 1.1) и <Code> (SOAP 1.2)

Код (SOAP 1.1)Значение (SOAP 1.2)Кем генерируетсяОписание
soap:VersionMismatchsoap:VersionMismatchЛюбойНесовместимая версия SOAP (например, 1.2-сообщение пришлось в 1.1-endpoint).
soap:MustUnderstandsoap:MustUnderstandПолучательЗаголовок с mustUnderstand="1" не распознан.
soap:Clientsoap:SenderСерверОшибка в запросе клиента (некорректные данные, отсутствует обязательный параметр).
soap:Serversoap:ReceiverСерверОшибка на стороне сервера (исключение, БД недоступна и т.п.).

🔸 В SOAP 1.2 введены вложенные Subcode, что позволяет детализировать причину:

  • soap:Sender + ns:AuthenticationFailed
  • soap:Receiver + ns:DatabaseTimeout

🔹 <detail> / <Detail>

  • Обязателен только при faultcode = Client/Server (SOAP 1.1) или Code ∈ {Sender, Receiver} (SOAP 1.2).
  • Должен содержать прикладные данные (не soap:*).
  • Не должен включать данные, нарушающие безопасность.

6. Привязка к HTTP — как SOAP передаётся по сети

SOAP не определяет транспорт, но HTTP — самая распространённая привязка (binding). Спецификации:

  • SOAP 1.1 → Simple Object Access Protocol (SOAP) 1.1, Section 6
  • SOAP 1.2 → SOAP Version 1.2 Part 2: Adjuncts, Section 7

🔹 HTTP-заголовки (обязательные и рекомендуемые)

ЗаголовокОбязательностьПример значенияПримечания
Content-Type✅ Обязателенtext/xml; charset=utf-8 (SOAP 1.1) application/soap+xml; charset=utf-8 (SOAP 1.2)Для SOAP 1.2 charset опционален, но рекомендован. При наличии вложений (MTOM) — multipart/related.
SOAPAction⚠ Только в SOAP 1.1 ❌ Удалён в SOAP 1.2"http://example.com/GetUser"Указывает намерение запроса. Мог быть пустым (""), но не должен отсутствовать. В SOAP 1.2 роль SOAPAction заменяет заголовок Content-Type + элемент <wsa:Action> (WS-Addressing).
Content-Length✅ Обязателен (если не chunked)1842Стандартный HTTP-заголовок, но критичен для парсинга.
Host✅ Обязателен (HTTP/1.1+)api.example.comСтандартный заголовок, но участвует в маршрутизации.

Различие SOAP 1.1 / 1.2 в HTTP:

  • В SOAP 1.2 SOAPAction заменён на параметр action в Content-Type, например:
    application/soap+xml; charset=utf-8; action="http://example.com/GetUser"
    Однако на практике многие серверы (в т.ч. .NET ASMX, Java Metro) игнорируют этот параметр и полагаются на корневой элемент в <Body> или wsa:Action.

🔹 HTTP-статусы и их интерпретация

СтатусОжидаемое содержимое телаКомментарий
200 OKКорректный SOAP-ответ (<Body> с результатом или <Fault>)Нормальный сценарий.
500 Internal Server Error<soap:Fault> (рекомендуется) или HTMLЧасто возвращается при необработанном исключении.
400 Bad Request<soap:Fault> с soap:Client / soap:SenderНекорректный XML, нарушение XSD-схемы и т.д.
415 Unsupported Media TypeЕсли Content-Type не text/xml (1.1) / application/soap+xml (1.2).
501 Not Implemented<soap:Fault> с soap:VersionMismatchЕсли сервер не поддерживает версию SOAP (например, пришёл 1.2-запрос в 1.1-эндпоинт).

🔹 Важно: Тело ответа всегда должно быть валидным SOAP-документом (даже при 5xx), иначе клиент не сможет корректно обработать ошибку.


7. Вложения и двоичные данные (Binary Attachments)

SOAP — текстовый XML-протокол. Передача бинарных данных (изображения, PDF, файлы) требует кодирования или упаковки.

Способы:

СпособСтандартОписание
Base64-вложение в XMLНестандартный, но распространённый<data>YWJj...</data> — просто, но +33% объём, высокий overhead парсинга. Подходит для небольших данных (<100 КБ).
SwA (SOAP with Attachments)Устаревший (RFC 2387 + SOAP 1.1 Note)multipart/related: SOAP-сообщение + MIME-вложения. Не поддерживается WSDL 2.0, несовместим с MTOM.
MTOM (Message Transmission Optimization Mechanism)✅ W3C Recommendation (2005)Оптимизирует xsd:base64Binary/xsd:hexBinary в XOP (XML-binary Optimized Packaging). Использует multipart/related, но совместим с WSDL и XSD.
XOP (XML-binary Optimized Packaging)✅ W3C (часть MTOM)Стандартная замена base64 на <xop:Include href="cid:..."/>. MTOM — это XOP + HTTP-привязка.

🔹 Пример MTOM/XOP (в SOAP 1.2)

HTTP-заголовки:

Content-Type: multipart/related;
type="application/xop+xml";
start="<root.message@cxf.apache.org>";
start-info="application/soap+xml; charset=utf-8";
boundary="uuid:12345678-90ab-cdef-1234-567890abcdef"

Тело сообщения:

--uuid:12345678-90ab-cdef-1234-567890abcdef
Content-Type: application/xop+xml; charset=utf-8; type="application/soap+xml"
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<ns1:UploadDocument xmlns:ns1="http://example.com/">
<document>
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
href="cid:document.pdf@example.com"/>
</document>
</ns1:UploadDocument>
</soap:Body>
</soap:Envelope>

--uuid:12345678-90ab-cdef-1234-567890abcdef
Content-Type: application/pdf
Content-Transfer-Encoding: binary
Content-ID: <document.pdf@example.com>

%PDF-1.4...
--uuid:12345678-90ab-cdef-1234-567890abcdef--

🔸 Поддержка:

  • .NET: basicHttpBinding / wsHttpBinding с messageEncoding="Mtom"
  • Java (JAX-WS): аннотация @MTOM или настройка BindingProvider
  • Apache CXF: <jaxws:binding> с <xjc:extension> и mtom-enabled="true"

8. WSDL и SOAP: как описывается интерфейс

WSDL (Web Services Description Language) — XML-документ, описывающий контракт веб-сервиса, включая SOAP-привязки.

Структура WSDL 1.1 (кратко):

<definitions targetNamespace="http://example.com/">
<types> <!-- XSD-схемы типов -->
<xsd:schema>...</xsd:schema>
</types>

<message name="GetUserRequest">
<part name="parameters" element="tns:GetUser"/>
</message>

<portType name="UserServicePortType">
<operation name="GetUser">
<input message="tns:GetUserRequest"/>
<output message="tns:GetUserResponse"/>
</operation>
</portType>

<binding name="UserServiceBinding" type="tns:UserServicePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetUser">
<soap:operation soapAction="http://example.com/GetUser"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>

<service name="UserService">
<port name="UserServicePort" binding="tns:UserServiceBinding">
<soap:address location="https://api.example.com/user"/>
</port>
</service>
</definitions>

🔹 Ключевые атрибуты в <soap:binding> и <soap:operation>

ЭлементАтрибутВозможные значенияПримечание
<soap:binding>stylerpc | documentdocument — современный стандарт (сообщение = XSD-элемент). rpc — устаревший (сообщение = вызов метода).
<soap:binding>transporthttp://schemas.xmlsoap.org/soap/http | http://www.w3.org/2003/05/soap/bindings/HTTP/Первое — SOAP 1.1, второе — SOAP 1.2.
<soap:operation>soapActionURIТребуется в WSDL 1.1 для SOAP 1.1. В WSDL 2.0 заменён на wsdlx:safe и http:operation.
<soap:body>useliteral | encodedliteral — данные соответствуют XSD. encoded — использует soap:encodingStyle (устарело, несовместимо с WS-I BP).
<soap:body>partsсписок имён <part>Опционален, если один параметр.

🔹 WS-I Basic Profile 1.1 запрещает:

  • use="encoded"
  • style="rpc"
  • soap:encodingStyle → Рекомендуется только document/literal.

9. Безопасность: WS-Security (WSS)

SOAP не содержит встроенной безопасности. WS-Security (OASIS Standard) — основной механизм защиты сообщений.

Элементы в <soap:Header>:

ЭлементПространство имёнНазначение
<wsse:Security>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsdКонтейнер для всех элементов безопасности.
<wsse:UsernameToken>то жеАутентификация по логину/паролю.
<wsse:BinarySecurityToken>то жеСертификат (X.509), SAML-утверждение, Kerberos-тикет.
<ds:Signature>http://www.w3.org/2000/09/xmldsig#Цифровая подпись (чаще всего enveloped).
<xenc:EncryptedData>http://www.w3.org/2001/04/xmlenc#Шифрование элемента (чаще <Body> или <UsernameToken>).
<wsu:Timestamp>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsdЗащита от replay-атак.

🔹 Пример <wsse:UsernameToken> (plain text — не для production):

<wsse:Security soap:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>admin</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
secret
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>

🔹 Рекомендуемые Type для <wsse:Password>:

Type URIОписание
#PasswordTextОткрытый текст (только с TLS).
#PasswordDigestBase64(SHA-1(nonce + created + password)). Требует <wsse:Nonce> и <wsu:Created>.
#PasswordDigest + Nonce + Created — стандартный способ без TLS на уровне канала.

🔹 <wsu:Timestamp> (обязателен при PasswordDigest и для защиты от replay):

<wsu:Timestamp wsu:Id="TS-1"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2025-11-21T10:00:00Z</wsu:Created>
<wsu:Expires>2025-11-21T10:05:00Z</wsu:Expires>
</wsu:Timestamp>

🔸 Поддержка:

  • .NET: WSE 3.0 (устарело), CustomBinding с SecurityBindingElement, или wsHttpBinding + MessageCredentialType.UserName.
  • Java: Apache WSS4J (в CXF), Metro @Policy.

10. WS-Addressing (W3C Recommendation, 2006)

SOAP изначально не определял адресацию сообщений — откуда, куда, куда отвечать, куда отправлять ошибки.
WS-Addressing (WSA) решает эти задачи независимо от транспорта (HTTP, JMS, SMTP), обеспечивая маршрутизацию, корреляцию и асинхронность.

Основные элементы в <soap:Header>:

ЭлементОбязательностьПример значенияОписание
<wsa:To>https://api.example.com/UserServiceКонечная точка, которой адресовано сообщение. Аналог HTTP URL, но в сообщении.
<wsa:Action>✅ (в wsaw:UsingAddressing)http://example.com/UserService/GetUserRequestУказывает намерение (semantic), заменяет SOAPAction. Используется для диспетчеризации операций.
<wsa:MessageID>urn:uuid:123e4567-e89b-12d3-a456-426614174000Уникальный идентификатор сообщения (для логирования, дедупликации).
<wsa:ReplyTo><wsa:Address>http://client.example.com/callback</wsa:Address>Куда отправить ответ (асинхронный вызов). Если отсутствует — синхронный (ответ в HTTP response).
<wsa:FaultTo>аналогично ReplyToКуда отправить Fault, если отличается от ReplyTo.
<wsa:From>аналогичноКто отправитель (для аудита, маршрутизации).
<wsa:RelatesTo><wsa:RelatesTo RelationshipType="http://www.w3.org/2005/08/addressing/reply">urn:uuid:...Корреляция: ответ → запрос, ошибка → запрос и т.д.

Пространства имён:

  • Основное: http://www.w3.org/2005/08/addressing (рекомендуемое)
  • Устаревшее: http://schemas.xmlsoap.org/ws/2004/08/addressing

🔹 Специальные URI-значения:

URIНазначение
http://www.w3.org/2005/08/addressing/anonymousОтвет в том же HTTP-соединении (синхронно). Значение по умолчанию для ReplyTo, если не указан.
http://www.w3.org/2005/08/addressing/noneНе отправлять ответ (fire-and-forget).
http://www.w3.org/2005/08/addressing/faultОтправлять Fault в FaultTo, даже если ReplyTo указан.

🔹 Пример асинхронного вызова:

<soap:Header>
<wsa:MessageID>urn:uuid:1111</wsa:MessageID>
<wsa:Action>http://example.com/LongOperation</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>https://client.example.com/async-response</wsa:Address>
</wsa:ReplyTo>
<wsa:FaultTo>
<wsa:Address>https://client.example.com/async-fault</wsa:Address>
</wsa:FaultTo>
</soap:Header>
<soap:Body>
<ns:LongOperationRequest>...</ns:LongOperationRequest>
</soap:Body>

🔸 Поддержка:

  • .NET: CustomBinding с TextMessageEncodingBindingElement + HttpTransportBindingElement, и ChannelFactory<IDuplexChannel>; или wsHttpBinding с useDefaultWebProxy="false" и listenUri.
  • Java (CXF): <jaxws:server> + <jaxws:properties>org.apache.cxf.ws.addressing.MAPAggregator=true.

11. WS-ReliableMessaging (WS-RM, OASIS Standard)

Обеспечивает гарантированную, упорядоченную, без дубликатов доставку SOAP-сообщений поверх ненадёжных транспортов.

Основные концепции:

  • RM Source — отправитель
  • RM Destination — получатель
  • Sequence — упорядоченная серия сообщений (идентифицируется Identifier)
  • Acknowledgement — подтверждение получения (<wsrm:SequenceAcknowledgement>)

Элементы в <soap:Header>:

ЭлементОписание
<wsrm:Sequence>В запросе: Identifier + MessageNumber (1,2,3…). В ответе — может отсутствовать.
<wsrm:SequenceAcknowledgement>Список полученных MessageNumber; может быть битовой картой или диапазонами.
<wsrm:CreateSequence>Инициализация новой последовательности (в отдельном handshake-обмене).
<wsrm:CloseSequence>Завершение последовательности.

Пример <wsrm:Sequence>:

<wsrm:Sequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>urn:uuid:abcd-1234</wsrm:Identifier>
<wsrm:MessageNumber>3</wsrm:MessageNumber>
</wsrm:Sequence>

🔹 Поведение:

  • При потере сообщения — RM Destination не подтверждает его номер → RM Source повторяет.
  • При дубликате — MessageNumber уже учтён → игнорируется.
  • При нарушении порядка — сообщения буферизуются до прихода предыдущих.

🔸 Поддержка:

  • .NET: NetTcpBinding с reliableSession.Enabled = true; wsHttpBinding — только если кастомизировано (не из коробки).
  • Java: Apache Sandesha2 (в CXF), Metro WS-RM.

Ограничения: WS-RM работает только на уровне сообщений, не обеспечивает транзакционной целостности. Для этого — см. WS-AtomicTransaction.


12. WS-Coordination и WS-AtomicTransaction

Для участия SOAP-сервисов в распределённых транзакциях (2PC — two-phase commit).

Архитектура:

  • Инициатор создаёт координационный контекст через Activation Service (wscoor:CreateCoordinationContext).
  • Сервисы регистрируются в контексте через Registration Service (wscoor:Register).
  • Координатор управляет фазами PrepareCommit / Rollback.

Пространства имён:

  • Coordination: http://schemas.xmlsoap.org/ws/2004/10/wscoor
  • AtomicTransaction: http://schemas.xmlsoap.org/ws/2004/10/wsat

Элемент в <soap:Header>:

<wscoor:CoordinationContext>
<wscoor:Identifier>urn:uuid:tx-789</wscoor:Identifier>
<wscoor:CoordinationType>
http://schemas.xmlsoap.org/ws/2004/10/wsat
</wscoor:CoordinationType>
<wscoor:RegistrationService>
<wsa:Address>https://coordinator.example.com/register</wsa:Address>
</wscoor:RegistrationService>
</wscoor:CoordinationContext>

Операции в теле:

  • <wsat:Prepare> → сервис отвечает <wsat:Prepared> / <wsat:Aborted>
  • <wsat:Commit> / <wsat:Rollback>

🔸 Поддержка:

  • .NET: System.Transactions + TransactionScope + WS-AtomicTransaction binding (только в enterprise-средах, напр. с MSDTC).
  • Java: Narayana (JBoss), Atomikos — через JTA + кастомные SOAP-перехватчики.

Практическое замечание: WS-AT редко используется в публичных API из-за сложности, latency и statefulness. Чаще применяют компенсирующие транзакции (Saga) или отказываются от распределённой транзакционности.


13. Профили совместимости и ограничения

🔹 WS-I Basic Profile 1.1 (и 2.0) — де-факто стандарт для совместимости

ТребованиеЗначение
Стиль сообщенияdocument/literal
Кодировкаuse="literal" (запрещено encoded)
soap:encodingStyle❌ запрещён
SOAPActionДолжен быть указан (может быть "")
WSDLДолжен быть валиден, один portType на binding, один port на service
Fault<faultcode> из стандартного набора, <detail> — только при Client/Server

🔹 WS-I Attachments Profile 1.0

  • Запрещает SwA
  • Рекомендует MTOM/XOP для бинарных данных
  • Требует указания Content-ID в xop:Include/@href

🔹 WS-I Security Profile 1.1

  • Разрешает только #PasswordText с TLS или #PasswordDigest с Nonce/Created
  • Требует wsu:Timestamp при PasswordDigest
  • Запрещает подпись/шифрование без политики (wsse:Security без wsu:Id — недопустимо)

14. Отладка и инструменты

ИнструментВозможности
SoapUI (ReadyAPI)Генерация из WSDL, mocking, load testing, security testing (WS-Security), MTOM, WS-A, WS-RM.
Fiddler / CharlesПерехват HTTP(S), просмотр/редактирование raw SOAP, breakpoint-отладка.
WiresharkАнализ на уровне TCP/HTTP, фильтрация по xml, soap, wsa.
PostmanПоддержка SOAP (начиная с v8.0): импорт WSDL, raw XML, переменные, pre-request scripts для wsse:UsernameToken.
svcutil.exe (.NET)Генерация клиентского кода из WSDL: svcutil /t:metadata /serviceContract.
wsimport (JAX-WS)wsimport -keep -s src/ http://example.com/service?wsdl → генерация Java-классов.

🔹 Пример: подпись wsse:UsernameToken с PasswordDigest в Postman (Pre-request Script):

const crypto = require('crypto-js');
const nonce = CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Base64);
const created = new Date().toISOString();
const password = pm.environment.get("password");
const digest = CryptoJS.SHA1(
CryptoJS.enc.Base64.parse(nonce) +
CryptoJS.enc.Utf8.parse(created) +
CryptoJS.enc.Utf8.parse(password)
).toString(CryptoJS.enc.Base64);

pm.request.headers.add({
key: 'Content-Type',
value: 'text/xml;charset=UTF-8'
});

// Вставить в XML-тело:
// <wsse:Nonce EncodingType="...#Base64Binary">{{nonce}}</wsse:Nonce>
// <wsu:Created>{{created}}</wsu:Created>
// <wsse:Password Type="...#PasswordDigest">{{digest}}</wsse:Password>

15. Сравнение SOAP 1.1 и SOAP 1.2: таблица различий

КатегорияSOAP 1.1SOAP 1.2Комментарий
Пространство имён Envelopehttp://schemas.xmlsoap.org/soap/envelope/http://www.w3.org/2003/05/soap-envelopeКритично для валидации.
Fault-структураПлоская: <faultcode>, <faultstring>, <faultactor>, <detail>Иерархическая: <Code>Value/Subcode), <Reason> (множество <Text>), <Node>, <Role>, <Detail>SOAP 1.2 позволяет локализацию и детализацию ошибок.
HTTP Content-Typetext/xml (рекомендовано)application/soap+xmlВ 1.2 charset указывается в параметре charset=utf-8, не в заголовке Content-Type.
SOAPActionОбязательный HTTP-заголовокУдалён из спецификации; заменён на параметр action в Content-Type или wsa:ActionНа практике многие 1.2-серверы игнорируют action в Content-Type.
encodingStyleРазрешён (но не рекомендован)Удалён из схемы (атрибут * допускает его, но не интерпретируется)Использование encodingStyle нарушает WS-I BP.
Обработка неизвестных заголовковНе регламентированоВведён атрибут soap:relay: если 1, промежуточный узел передаёт заголовок дальше, даже если не понимает егоПовышает расширяемость.
Явный role (вместо actor)actor (URI)role (ограниченные URI: none, ultimateReceiver, next)Более строгая семантика маршрутизации.
Поддержка UnicodeНеявнаяЯвно указано, что XML-декларация encoding="UTF-8" предпочтительнаUTF-8 — обязательный минимум реализации.
Ошибки верификации XMLНе специфицированоВведён код soap:DataEncodingUnknown (в Subcode)Для случаев, когда кодировка не поддерживается.

🔹 Совместимость:

  • Сервер SOAP 1.2 не обязан принимать SOAP 1.1-сообщения.
  • Реализации (например, Apache CXF, .NET CoreWCF) часто поддерживают обе версии на одном endpoint’е, но это — расширение, а не стандарт.

16. Поддержка в фреймворках и стеках

🔹 .NET

ТехнологияВерсияПоддержка SOAPОграничения
ASMX (Web Services).NET Framework 1.0–4.8SOAP 1.1, document/literal, базовый WS-SecurityУстарело, не поддерживает MTOM без костылей, нет WS-A/WS-RM.
WCF.NET Framework 3.0–4.8Полная: SOAP 1.1/1.2, MTOM, WS-Security (WSS 1.0/1.1), WS-A, WS-RM, WS-ATТребует customBinding для тонкой настройки. Не поддерживается в .NET Core 1–2.
CoreWCF.NET 5+ (community)Порт WCF: basicHttpBinding, wsHttpBinding, MTOM, частично WS-SecurityАктивно развивается; WS-RM и WS-AT — в roadmap.
HttpClient + ручная сериализацияЛюбаяПолный контроль: можно собрать любой SOAP-пакетТрудоёмко; рекомендуется только для интеграций с legacy.

🔹 Java

ТехнологияСтекПоддержка
JAX-WS (Metro)Java EE / Jakarta EESOAP 1.1/1.2, MTOM, WS-Security (через @Policy), WS-A (частично)
Apache CXFSpring, standaloneПолная: WS-Security (WSS4J), WS-A, WS-RM (Sandesha2), WS-AT (Narayana), MTOM/XOP
Spring-WSSpring Framework«Contract-first» (только document/literal), MTOM, WS-Security (через WSS4J), но без WSDL generation

🔹 Python

БиблиотекаПоддержкаКомментарий
zeepSOAP 1.1/1.2, WSDL 1.1/2.0, MTOM (частично), WS-Security (UsernameToken, Timestamp, BinarySecurityToken)Активно поддерживается, типизация через xsd. Лучший выбор.
pysimplesoapSOAP 1.1, базовый WS-SecurityУстаревшая, минимальная поддержка.
suds-jurkoSOAP 1.1, WSDL, нет MTOM/WS-SecurityНе поддерживается с 2014 г.

🔹 Node.js / JS/TS

БиблиотекаПоддержка
node-soapSOAP 1.1, WSDL, базовый UsernameToken, MTOM (через multipart)
strong-soapФорк node-soap: SOAP 1.2, MTOM, PasswordDigest, WSDL 2.0

17. Анти-паттерны и типичные ошибки

ОшибкаПоследствиеКак исправить
<data><![CDATA[...]]></data> внутри xsd:stringНекорректный XML при парсинге: CDATA не сохраняется в объектной модели; нарушает XSD-валидацию (xs:string не допускает CDATA как особую конструкцию).Использовать &lt;, &gt;, &amp; — XML-парсер сам декодирует.
xmlns="" внутри <Body>Элемент попадает в пустое пространство имён, нарушает правило «всё в Body — не в soap-env». Многие фреймворки (CXF, WCF) отклоняют.Явно указывать xmlns:ns="..." и использовать ns:element.
&nbsp; в XML-данныхНестандартная entity — не определена в XML без DTD. Вызовет SAXParseException.Использовать &#160; (числовой код) или (пробел).
encodingStyle в SOAP 1.2Не интерпретируется; вызывает предупреждения в логах.Удалить. Типизация — через XSD.
Отсутствие mustUnderstand="1" у критичных заголовковПромежуточный узел проигнорирует заголовок → нарушение безопасности/транзакции.Всегда указывать soap:mustUnderstand="1" для wsse:Security, wsrm:Sequence, wscoor:CoordinationContext.
<detail> без soap:Client/ServerНарушение спецификации: <detail> разрешён только при faultcode ∈ {Client, Server}.Удалять <detail> при VersionMismatch/MustUnderstand.

18. Когда оставаться на SOAP, а когда мигрировать

КритерийРекомендацияОбоснование
Требуется ACID-транзакция через сервисы✅ SOAP + WS-ATREST не предоставляет стандартизированного 2PC.
Интеграция с гос/банковскими системами (ЕПГУ, Банк России, СМЭВ 3.0)✅ SOAPТребования ГОСТ Р 7.0.97-2016, СМЭВ — строго SOAP/WSDL/WS-Security.
Необходима гарантированная доставка (без потерь)✅ SOAP + WS-RMREST требует реализации на уровне приложения (например, idempotency keys + лог).
Микросервисы внутри одного домена, agile-разработка❌ → REST/GraphQL/gRPCSOAP замедляет итерации: WSDL, codegen, версионирование контрактов.
Высокая нагрузка, low-latency❌ → gRPC/protobufSOAP/XML — высокий overhead (парсинг, размер).
Публичное API для мобильных/веб-клиентов❌ → REST/JSONПоддержка SOAP в браузере — только через прокси; JSON легче для обработки.

🔹 Эмпирическое правило:
— Если контрагент предоставляет только WSDL → используйте SOAP.
— Если вы владеете обеими сторонами и нет legacy-ограничений → оцените gRPC или REST+OpenAPI.