SOAP Header鉴权需客户端显式注入Token并严格匹配服务端WSDL声明的Header结构、命名空间及大小写;zeep用wsse插件、JAX-WS写SOAPHandler、.NET用OperationContextScope手动塞;须解析SOAPFault而非仅看HTTP状态码。

SOAP Header 里加 Token 鉴权,不是往 XML 里随便塞个 Token 字段就行——服务端必须明确声明能读这个字段,客户端还得确保它真进到了 Header 而不是被框架吞掉或错放到 Body 里。
怎么让 Token 出现在 SOAP Header 而不是 Body
多数 SOAP 客户端(比如 Java 的 JAX-WS、.NET 的 HttpClient + SoapClient、Python 的 zeep)默认只把业务参数放 Body,Header 需显式注入。不手动干预,Token 就会“消失”在传输层之外。
-
zeep:用wsse插件最稳,别手写 XML;直接传UsernameToken或自定义Plugin注入Header -
JAX-WS:得写Handler实现SOAPHandler<soapmessagecontext></soapmessagecontext>,在handleRequest里调用context.getMessage().getSOAPHeader().addHeaderElement() - .NET
SoapClient:重载GetBinding或用OperationContextScope+MessageHeader手动塞,别依赖ClientCredentials自动行为(它默认走 WS-Security 的wsse:UsernameToken,不是裸 Token)
Token 放 Header 时的命名和命名空间必须和服务端严格一致
服务端 WSDL 里定义的 Header 元素名、targetNamespace、是否需要 mustUnderstand="1",客户端一丁点对不上,就会被直接拒收,甚至不报错——请求静默失败,日志里只显示“Empty response”或“500 Internal Server Error”。
- 先看 WSDL 的
<wsdl:binding>里有没有<soap:header>块,记下message名和part名 - XML 中 Token 元素名必须和
part名完全一致(区分大小写),比如服务端要<AuthHeader>,你写成<authHeader>就无效 - 命名空间 URI 必须一字不差,常见坑:
http://example.com/和http://example.com(末尾斜杠)被视为不同 NS
Token 过期或格式错误时,SOAP 错误码不统一,容易误判
不同服务端对 Header 鉴权失败的响应差异很大:401 Unauthorized、500 带 SOAPFault、甚至直接返回空 200 OK + 空 Body。不能只看 HTTP 状态码,必须解析返回的 SOAPEnvelope 内容。
- 优先检查响应 XML 是否含
<soap:Fault>,再看<faultcode>是soap:Client还是soap:Server - 常见错误值:
InvalidSecurityToken、AuthenticationFailed、SecurityTokenExpired—— 这些都在<faultstring>或<detail>里,不是标准 HTTP header - 调试时用
curl -v或 Wireshark 抓原始 XML,别信 IDE 或工具生成的“简化响应”
真正难的不是拼出那个带 Token 的 XML,而是确认服务端到底认哪一套 Header 结构、哪个命名空间、哪种编码(Base64?JWT?明文?),以及它的验证逻辑是否在解析 Header 阶段就中断——这些细节,WSDL 不一定写全,得靠抓包+服务端日志交叉验证。










