使用Spring定制soapHeader以获取soap请求

时间:2015-10-26 12:58:08

标签: java xml spring web-services soap

我正在使用包含请求安全部分的自定义标头发出SOAP请求。 但请求现在包含两个标头,并抛出以下错误: [请求处理失败;嵌套异常是org.springframework.ws.soap.client.SoapFaultClientException:没有找到WS-Security标头]有根本原因

形成的标题是:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header><soapenv:Envelope xmlns:ser="dasdasdasd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><wsse:Security xmlns:wsse="asdasdasdas" soapenv:mustUnderstand="1">  <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-2"><wsse:Username>test</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">adasdasdasdasd</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">!@#!@#@#$@!#!@@%*(&*&^%#$@#</wsse:Nonce><wsu:Created>2014-09-04 T1015.41.649Z</wsu:Created></wsse:UsernameToken></wsse:Security></soapenv:Header></soapenv:Envelope></SOAP-ENV:Header><SOAP-ENV:Body><ns2:CreateSaleOrderRequest xmlns:ns2="http://uniware.unicommerce.com/services/"><ns2:SaleOrder><ns2:DisplayOrderCode>200</ns2:DisplayOrderCode></ns2:SaleOrder></ns2:CreateSaleOrderRequest></SOAP-ENV:Body></SOAP-ENV:Envelope>

上述请求的代码如下:

private static final String uri = "http://requestb.in/1eh2un81";

public String createSaleOrder(Suborder suborder)
{
    SaleOrder saleorder = new SaleOrder();
    saleorder = setSaleOrderObject(suborder);
    CreateSaleOrderRequest request = new CreateSaleOrderRequest();
    request.setSaleOrder(saleorder);
    String response = this.getWebServiceTemplate().marshalSendAndReceive(uri, request, 
            new WebServiceMessageCallback() {
                public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException 
        {
                    SoapMessage soapmessage = (SoapMessage)message;                
                    SoapHeader header = soapmessage.getSoapHeader();
                    //soapmessage.getEnvelope().addAttribute(, "soapenv");

                    StringBuilder soapheader = new StringBuilder();
                    soapheader.append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"zsdasdasdasd">");
                    soapheader.append("<soapenv:Header>");
                    soapheader.append("<wsse:Security soapenv:mustUnderstand=\"1\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">  ");
                    soapheader.append("<wsse:UsernameToken wsu:Id=\"UsernameToken-2\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">");
                    soapheader.append("<wsse:Username>test</wsse:Username>");
                    soapheader.append("<wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">adasdasdasdasd</wsse:Password>");
                    soapheader.append("<wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">!2312312!@#!@#!#$@#%R</wsse:Nonce>");
                    soapheader.append("<wsu:Created>2014-09-04 T1015.41.649Z</wsu:Created>");
                    soapheader.append("</wsse:UsernameToken>");
                    soapheader.append("</wsse:Security>");
                    soapheader.append("</soapenv:Header>");
                    soapheader.append("</soapenv:Envelope>");


                    StringSource HeaderSource = new StringSource(soapheader.toString());
                    Transformer transformer = TransformerFactory.newInstance().newTransformer();
                    transformer.transform(HeaderSource,header.getResult());

                    }
    }).toString();
    System.out.println(response);

请建议我如何解决此错误.TIA!

1 个答案:

答案 0 :(得分:0)

嗯,如果你使用弹簧,你就必须这样做..你的xml里面应该有你应该拥有的:

    <bean id="YourWsClientBean" class="eu.europa.acer.aris.dciws.client.DciWsClient">
        <constructor-arg ref="webServiceTemplate"></constructor-arg>
    </bean>


    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
        <constructor-arg ref="messageFactory"/>
        <property name="marshaller" ref="marshaller"></property>
        <property name="unmarshaller" ref="unMarshaller"></property>

        <property name="messageSender">
            <bean
                class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
            </bean>
        </property>
         <!-- NON PROXY
         <property name="messageSender" ref = "httpSender"></property>    -->       
        <property name="defaultUri" value="https://testframework.test-acer-remit.eu/dci-ws/" />
        <property name="interceptors">
            <list>
                <ref bean="securityConfInterceptor" />

            </list>
        </property>
    </bean>

    <bean id="securityConfInterceptor" class="org.springframework.ws.soap.security.xwss.XwsSecurityInterceptor">
            <property name="policyConfiguration" value="classpath:securityPolicy.xml" />
            <property name="callbackHandlers">
                <!-- <bean id="keyStoreHandler" class="org.springframework.ws.soap.security.xwss.callback.KeyStoreCallbackHandler"> 
                    <property name="keyStore" ref="keyStore" /> <property name="privateKeyPassword" 
                    value="changeit" /> <property name="trustStore" ref="trustStore" /> </bean> -->
                <list>
                    <ref bean="keyStoreHandler"/> 
                </list>
            </property>
    </bean>
我想,marshaller和unmarshaller应该对你很清楚。 你案件中最重要的部分是

在securityPolicy.xml中,您将能够为传出的//传入消息定义您的欲望策略,无论是签名,用户名和密码等。

以下文件用于使用特定证书对请求进行签名。

<?xml version="1.0" encoding="UTF-8"?>
    <!-- <xwss:SecurityConfiguration dumpMessages="false" xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"> 
        <xwss:Sign includeTimestamp="false"> <xwss:X509Token certificateAlias="ceremp 
        staging ca"/> </xwss:Sign> </xwss:SecurityConfiguration> -->
    <xwss:SecurityConfiguration xmlns:xwss="http://java.sun.com/xml/ns/xwss/config">
        <!-- <xwss:RequireTimestamp maxClockSkew="60" timestampFreshnessLimit="300"/> 
            <xwss:RequireUsernameToken passwordDigestRequired="false" nonceRequired="false"/> 
            <xwss:Timestamp /> <xwss:UsernameToken name="mojo" password="mojopass" digestPassword="true" 
            useNonce="true"/> -->
        <xwss:Sign>
            <xwss:X509Token certificateAlias="acerprivate" /> 
            <!-- <xwss:X509Token certificateAlias="acer staging cert" /> -->
            <xwss:CanonicalizationMethod algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <xwss:SignatureMethod algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <xwss:SignatureTarget type="xpath"
                value="./SOAP-ENV:Envelope/SOAP-ENV:Body">
                <xwss:DigestMethod algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <xwss:Transform algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
                    <xwss:AlgorithmParameter name="XPATH"
                        value="./SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/ds:Signature[1]/ds:KeyInfo/wsse:SecurityTokenReference" />
                </xwss:Transform>
                <xwss:Transform
                    algorithm="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#STR-Transform">
                    <xwss:AlgorithmParameter name="CanonicalizationMethod"
                        value="http://www.w3.org/2001/10/xml-exc-c14n#" />
                </xwss:Transform>
            </xwss:SignatureTarget>
        </xwss:Sign>
    </xwss:SecurityConfiguration>

希望这能为你提供一个普遍的概念。

有时候,如果他们想让改变尽可能简单的话,我建议一些新的同事采取肮脏的选择。 例如。这是来自春季论坛 - &gt;

        public void sendAndReceiveXMLPayload(String xmlFileNamePath) throws IOException {

        ClassPathResource
            classPathResource =
                new ClassPathResource(xmlFileNamePath);

        Source
            requestSource = 
                new ResourceSource(classPathResource);

        StringResult
            result =
                new StringResult();

        getWebServiceTemplate().
            sendSourceAndReceiveToResult(
                requestSource,  
                new WSSESecurityHeaderRequestWebServiceMessageCallback(),
                result
            );  
    }

通知 WSSESecurityHeaderRequestWebServiceMessageCallback

定义一个

public class WSSESecurityHeaderRequestWebServiceMessageCallback implements WebServiceMessageCallback {

    public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {

        try {

            // Assumption: We are using the default SAAJWebMessageFactory 

            SaajSoapMessage
                saajSoapMessage =
                    (SaajSoapMessage)message;

            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"
                    );

            // Add "Security" soapHeaderElement to soapHeader
            SOAPHeaderElement
                soapHeaderElement =
                    soapHeader.addHeaderElement(headerElementName);

            // This may be important for some portals!
            soapHeaderElement.setActor(null);

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

            // Add username to usernameToken
            SOAPElement
                userNameSOAPElement =
                    usernameTokenSOAPElement.addChildElement("Username");

            userNameSOAPElement.addTextNode("myUserName");

            // Add password to usernameToken
            SOAPElement
                passwordSOAPElement =
                    usernameTokenSOAPElement.addChildElement("Password");

            passwordSOAPElement.addTextNode("myPassword");

        } catch (SOAPException soapException) {
            throw new RuntimeException("WSSESecurityHeaderRequestWebServiceMessageCallback", soapException);
        }
    }
}

在本课程中,您可以根据自己的需要更改自己对标题的处理方式并完成...