You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WS SOAP请求Header添加ValueType属性失败求助

问题:Spring SOAP客户端无法添加BinarySecurityToken的ValueType属性

服务端要求的SOAP请求示例

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:BinarySecurityToken xmlns:wsst="http://www.ibm.com/websphere/appserver/tokentype/5.0.2" ValueType="wsst:LTPA">generated_token</wsse:BinarySecurityToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      ...
   </soapenv:Body>
</soapenv:Envelope>

实现的回调类代码

@Component
public class CrmBinarySecurityTokenHeaderCallback implements WebServiceMessageCallback {

    @Autowired
    private TokenGenerator tokenGenerator;

    @Override
    public void doWithMessage(WebServiceMessage webServiceMessage) throws IOException, TransformerException {
        String securityToken = tokenGenerator.getToken();

        try {
            SaajSoapMessage saajSoapMessage = (SaajSoapMessage) webServiceMessage;
            SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
            SOAPPart soapPart = soapMessage.getSOAPPart();
            SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
            SOAPHeader soapHeader = soapEnvelope.getHeader();

            Name headerElementName = soapEnvelope.createName("Security", "wsse",
                    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

            SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);
            SOAPElement securityTokenSoapElement = soapHeaderElement.addChildElement("BinarySecurityToken", "wsse");
            securityTokenSoapElement.addNamespaceDeclaration("wsst", "http://www.ibm.com/websphere/appserver/tokentype/5.0.2");

            QName valueType = securityTokenSoapElement.createQName("ValueType", "wsst");
            securityTokenSoapElement.addAttribute(valueType, "LTPA");

            securityTokenSoapElement.addTextNode(securityToken);

            soapMessage.saveChanges();
        } catch (SOAPException e) {
            throw new RuntimeException(e);
        }

    }
}

当前生成的SOAP请求(缺少ValueType属性)

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header>
      <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
         <wsse:BinarySecurityToken xmlns:wsst="http://www.ibm.com/websphere/appserver/tokentype/5.0.2">
             generated_token
         </wsse:BinarySecurityToken>
      </wsse:Security>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body>
      ...
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

问题说明

当前生成的请求与服务端要求几乎一致,但<wsse:BinarySecurityToken>元素始终无法添加ValueType="wsst:LTPA"属性,尝试使用SOAPElement.addAttribute()方法无效,求解决思路。


解决方法

问题核心是ValueType属性的命名空间归属错误:

  • 在WS-Security规范中,ValueType是BinarySecurityToken的标准属性,属于wsse命名空间,而非wsst。之前的代码错误地将属性归到wsst命名空间下,导致SOAP引擎未正确渲染该属性。
  • 属性值wsst:LTPA中的wsst是引用已声明的令牌类型命名空间,和属性本身的命名空间无关。

修改后的关键代码

替换原有的属性添加代码为:

// 使用wsse命名空间创建ValueType的QName
QName valueType = soapEnvelope.createQName("ValueType", "wsse");
// 属性值为wsst:LTPA,引用已声明的wsst命名空间
securityTokenSoapElement.addAttribute(valueType, "wsst:LTPA");

完整修改后的回调类

@Component
public class CrmBinarySecurityTokenHeaderCallback implements WebServiceMessageCallback {

    @Autowired
    private TokenGenerator tokenGenerator;

    @Override
    public void doWithMessage(WebServiceMessage webServiceMessage) throws IOException, TransformerException {
        String securityToken = tokenGenerator.getToken();

        try {
            SaajSoapMessage saajSoapMessage = (SaajSoapMessage) webServiceMessage;
            SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
            SOAPPart soapPart = soapMessage.getSOAPPart();
            SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
            SOAPHeader soapHeader = soapEnvelope.getHeader();

            Name headerElementName = soapEnvelope.createName("Security", "wsse",
                    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

            SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);
            SOAPElement securityTokenSoapElement = soapHeaderElement.addChildElement("BinarySecurityToken", "wsse");
            securityTokenSoapElement.addNamespaceDeclaration("wsst", "http://www.ibm.com/websphere/appserver/tokentype/5.0.2");

            // 修正ValueType属性的命名空间
            QName valueType = soapEnvelope.createQName("ValueType", "wsse");
            securityTokenSoapElement.addAttribute(valueType, "wsst:LTPA");

            securityTokenSoapElement.addTextNode(securityToken);

            soapMessage.saveChanges();
        } catch (SOAPException e) {
            throw new RuntimeException(e);
        }

    }
}

修改后重新生成的请求将包含正确的ValueType="wsst:LTPA"属性,符合服务端要求。


内容的提问来源于stack exchange,提问作者Alvaro Pedraza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:42:19