【问题标题】:Spring-WS SOAP header prefix issuesSpring-WS SOAP 标头前缀问题
【发布时间】:2018-09-19 13:42:39
【问题描述】:

我正在开发一个 Spring-WS 项目,我正在尝试使用某个 SOAP 服务,但是我遇到了请求的 Header 标记的一些问题。
PS:我在 SOAP UI 上运行了相同的请求,它运行良好。

这是我运行的代码:

JAXBElement<ChangeOtherIDsRequestType> request = createRequestBody();

    WebServiceTemplate template = new WebServiceTemplate(marshaller);
    template.setDefaultUri(URI);
    @SuppressWarnings({ "unchecked" })
    JAXBElement<ChangeOtherIDsResponseType> response = (JAXBElement<ChangeOtherIDsResponseType>) template
            .marshalSendAndReceive(request, new WebServiceMessageCallback() {

                @Override
                public void doWithMessage(WebServiceMessage message) {
                    Instant instant = Instant.now();

                    SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
                    SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
                    SOAPPart soapPart = soapMessage.getSOAPPart();
                    try {
                        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");

                        // Add "Security" soapHeaderElement to soapHeader
                        SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);
                        soapHeaderElement.setMustUnderstand(true);
                        soapHeaderElement.addNamespaceDeclaration("wsu",
                                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

                        // Add usernameToken to "Security" soapHeaderElement
                        SOAPElement usernameTokenSOAPElement = soapHeaderElement.addChildElement("UsernameToken",
                                "wsse");

                        // Add username to usernameToken
                        QName userQname = soapHeaderElement.createQName("Username", "wsse");
                        SOAPElement userNameSOAPElement = usernameTokenSOAPElement.addChildElement(userQname);
                        userNameSOAPElement.addTextNode("username");
                        // Add password to usernameToken
                        QName passwordQname = usernameTokenSOAPElement.createQName("Password", "wsse");
                        SOAPElement passwordSOAPElement = usernameTokenSOAPElement.addChildElement("Password");
                        passwordSOAPElement.setAttribute("Type",
                                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
                        passwordSOAPElement.addTextNode("password");
                        // Add Nonce to usernameToken.
                        QName nonceQname = soapHeaderElement.createQName("Nonce", "wsse");
                        SOAPElement nonceSOAPElement = usernameTokenSOAPElement.addChildElement("Nonce");
                        nonceSOAPElement.setAttribute("EncodingType",
                                "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");

                        // Add Created to usernameToken.
                        QName createdQname = soapHeaderElement.createQName("Created", "wsu");
                        SOAPElement createdElement = usernameTokenSOAPElement.addChildElement(createdQname);
                        createdElement.addTextNode(instant.toString());
                    } catch (SOAPException | UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
            });
    template.marshalSendAndReceive(URI, request);  

此代码应该在请求中添加 Header 标记,它用于通过“用户名”和“密码”对用户进行身份验证。
我期望的结果与 SOAP UI 为同一请求生成的结果相同。结果是这样的:

<SOAP-ENV:Header>
<wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <wsse:UsernameToken wsu:Id="UsernameToken-C17C5A667A3F11A8DA153735499778322">
        <wsse:Username>username</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
        <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Tl6jznnHitsSE9F16FWTsw==</wsse:Nonce>
        <wsu:Created>2018-09-19T11:03:17.783Z</wsu:Created>
    </wsse:UsernameToken>
</wsse:Security>

但是我得到的结果是这样的:

<SOAP-ENV:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
        <wsse:UsernameToken>
            <wsse:Username>username</wsse:Username>
            <Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</Password>
            <Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"> </Nonce>
            <wsu:Created>2018-09-19T11:02:21.918Z</wsu:Created>
        </wsse:UsernameToken>
    </wsse:Security>
</SOAP-ENV:Header>  

让我们看看我的结果中缺少一些东西,例如:

  • 标签“Password”和“Nonce”上的“wsse”前缀。
  • “用户名”标签上的“用户名令牌”属性。
  • “Nonce”标签的值。

我在尝试修复这些问题时遇到了一些问题,但我仍然有一些问题:

  1. 当我尝试将“wsse”前缀添加到“用户名”和“Nonce”标签时:整个“Header”标签消失。 (我使用了与“用户名”标签相同的技术)
  2. SOAP UI 如何生成“Nonce”值?
  3. SOAP UI 如何生成“UsernameToken”值?

最后的手段,有没有另一种方法来模拟 SOAP UI 请求?

提前致谢。

【问题讨论】:

  • 你为什么要嘲笑它,你为什么要这样做?您应该正确配置WebServiceTemplate并添加Wss4jSecurityInterceptor会添加标题,不要尝试自己做。

标签: java soap soapui spring-ws


【解决方案1】:

您正在尝试将安全性强加到您的请求中,而有一个拦截器和默认方式来执行此操作。为您的WebServiceTemplate 配置Wss4jSecurityInterceptor。

以下内容应该可以解决问题。

@Bean
public Wss4jSecurityInterceptor securityInterceptor() {
  Wss4jSecurityInterceptor interceptor = new Wss4jSecurityInterceptor();
  interceptor.setSecurementUsername("username");
  interceptor.setSecurementPassword("password");
  interceptor.setSecurementUsernameTokenNonce(true);
  interceptor.setSecurementActions("UsernameToken Timestamp");
  return interceptor;
}

然后将其注入您的WebServiceTemplate。这应该添加所需的标题,而您无需执行任何其他操作。理想情况下,您应该配置一次 WebServiceTemplate 并重复使用它。

@Bean
public WebServiceTemplate webServiceTemplate(Marshaller marshaller) {
    WebServiceTemplate wsTemplate = new WebServiceTemplate(marshaller);
    wsTemplate.setInterceptors(new ClientInterceptor[]{ securityInterceptor() });
    return wsTemplate;
}

然后在你的代码中使用预配置的WebServiceTemplate。

【讨论】:

  • 感谢 Deinum,它对我很有效。这似乎是一件基本的事情,但这是我第一次使用 SOAP 服务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-05
  • 2011-01-20
  • 2012-12-16
  • 1970-01-01
相关资源
最近更新 更多