【问题标题】:spring add soap header to endpoint's response春天将肥皂头添加到端点的响应中
【发布时间】:2015-04-12 15:25:00
【问题描述】:

我有这样的响应消息的 Spring Web 服务:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP-ENV:Header/>
       <SOAP-ENV:Body>
          <ns2:GetFlRpoResponse xmlns:ns2="http://webservices.example.com/siopso/schema">
             <ns2:ResponseInfo>
                <ns2:ResponseGenTime>2015-04-12T21:01:40.915+06:00</ns2:ResponseGenTime>
                <ns2:RequestID>549</ns2:RequestID>
                <ns2:Code>200</ns2:Code>
                <ns2:CodeDescription>Successful</ns2:CodeDescription>
             </ns2:ResponseInfo>
             <ns2:RPOInfo>
                <ns2:RPO>
                   <ns2:Barcode>XX780005595XX</ns2:Barcode>
                   <ns2:ReceptDate>2015-01-01+06:00</ns2:ReceptDate>
                   <ns2:Mailtype>Package</ns2:Mailtype>
                   <ns2:DelPostOffice>City19</ns2:DelPostOffice>
                   <ns2:Recipient>Someone1</ns2:Recipient>
                </ns2:RPO>
                <ns2:RPO>
                   <ns2:Barcode>XX183004561XX</ns2:Barcode>
                   <ns2:ReceptDate>2015-01-01+06:00</ns2:ReceptDate>
                   <ns2:Mailtype>Package2</ns2:Mailtype>
                   <ns2:DelPostOffice>City4</ns2:DelPostOffice>
                   <ns2:Recipient>Someone2</ns2:Recipient>
                   <ns2:RecipientAddr>Somewhere</ns2:RecipientAddr>
                </ns2:RPO>
             </ns2:RPOInfo>
             <ns2:FLRequestInfo>
                <ns2:Lastname>Ivanov</ns2:Lastname>
                <ns2:Firstname/>
                <ns2:Middlename/>
                <ns2:Barcode/>
                <ns2:FromDate>01.01.2015</ns2:FromDate>
                <ns2:ToDate>01.01.2015</ns2:ToDate>
             </ns2:FLRequestInfo>
          </ns2:GetFlRpoResponse>
       </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

对于这个响应,我的端点 responsepayload 看起来像这样:

@PayloadRoot(localPart = "GetFlRpoRequest", namespace = FL_TARGET_NAMESPACE)
public @ResponsePayload GetFlRpoResponse getFlRpo(@RequestPayload GetFlRpoRequest request) {
    System.out.println("Get FL !");
    GetFlRpoResponse response = siopsoService.getFlRpo(request.getFLRequestInfo());
    return response;
}

现在我需要对该响应进行签名并将签名信息添加到响应的标头中,并且必须是这样的:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
       <SOAP-ENV:Header>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
                <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34310-gost34311"/>
                <ds:Reference URI="#b0525e8a-dbcb-45da-abfd-d1bdecf6ccbb">
                    <ds:Transforms>
                        <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
                        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    </ds:Transforms>
                    <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34311"/>
                    <ds:DigestValue>valval=</ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>
                valuevalue==
            </ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>
                        valuevaluevalue=
                    </ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>
       </SOAP-ENV:Header>
       <SOAP-ENV:Body>
          <ns2:GetFlRpoResponse xmlns:ns2="http://webservices.example.com/siopso/schema">
             <ns2:ResponseInfo>
                <ns2:ResponseGenTime>2015-04-12T21:01:40.915+06:00</ns2:ResponseGenTime>
                <ns2:RequestID>549</ns2:RequestID>
                <ns2:Code>200</ns2:Code>
                <ns2:CodeDescription>Successful</ns2:CodeDescription>
             </ns2:ResponseInfo>
             <ns2:RPOInfo>
                <ns2:RPO>
                   <ns2:Barcode>XX780005595XX</ns2:Barcode>
                   <ns2:ReceptDate>2015-01-01+06:00</ns2:ReceptDate>
                   <ns2:Mailtype>Package</ns2:Mailtype>
                   <ns2:DelPostOffice>City19</ns2:DelPostOffice>
                   <ns2:Recipient>Someone1</ns2:Recipient>
                </ns2:RPO>
                <ns2:RPO>
                   <ns2:Barcode>XX183004561XX</ns2:Barcode>
                   <ns2:ReceptDate>2015-01-01+06:00</ns2:ReceptDate>
                   <ns2:Mailtype>Package2</ns2:Mailtype>
                   <ns2:DelPostOffice>City4</ns2:DelPostOffice>
                   <ns2:Recipient>Someone2</ns2:Recipient>
                   <ns2:RecipientAddr>Somewhere</ns2:RecipientAddr>
                </ns2:RPO>
             </ns2:RPOInfo>
             <ns2:FLRequestInfo>
                <ns2:Lastname>Ivanov</ns2:Lastname>
                <ns2:Firstname/>
                <ns2:Middlename/>
                <ns2:Barcode/>
                <ns2:FromDate>01.01.2015</ns2:FromDate>
                <ns2:ToDate>01.01.2015</ns2:ToDate>
             </ns2:FLRequestInfo>
          </ns2:GetFlRpoResponse>
       </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

为此,我已经像这样更改了我的响应负载:

@PayloadRoot(localPart = "GetFlRpoRequest", namespace = FL_TARGET_NAMESPACE)
    public @ResponsePayload GetFlRpoResponse getFlRpo(@RequestPayload DOMSource domSource,
            @RequestPayload GetFlRpoRequest request, SoapHeader header, MessageContext messageContext) throws Exception {

        System.out.println("Get FL !");

        Provider kncaProvider = new IolaProvider();
        Security.addProvider(kncaProvider);

        KeyStore ks = KeyStore.getInstance("pkcs12", kncaProvider.getName());

        ks.load(new FileInputStream(somekeyfile),somepass.toCharArray());

        PrivateKey privateKey = (PrivateKey) ks.getKey(somealias, somepass.toCharArray());

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        StreamResult streamResult = new StreamResult(byteArrayOutputStream);
        TransformerFactory copyTransformerFactory = TransformerFactory.newInstance();
        Transformer copyTransformer = copyTransformerFactory.newTransformer();
        copyTransformer.transform(domSource, streamResult);
        System.out.println(byteArrayOutputStream.toString());

        SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
        header = soapResponse.getSoapHeader();

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.newDocument();

        GetFlRpoResponse response = siopsoService.getFlRpo(request.getFLRequestInfo());

        JAXBContext context = JAXBContext.newInstance(GetFlRpoResponse.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.marshal(response, document);

        SOAPHeaderElement headerElement = null;
          NodeList nodes = document.getElementsByTagNameNS
            ("http://schemas.xmlsoap.org/soap/envelope/","Header");
          if(nodes.getLength() == 0)
          {
             System.out.println("Adding a SOAP Header Element");
             headerElement = document.createElementNS
               ("http://schemas.xmlsoap.org/soap/envelope/","Header");
             nodes = document.getElementsByTagNameNS
              ("http://schemas.xmlsoap.org/soap/envelope/","Envelope");
             if(nodes != null)
             {
                Element envelopeElement = (Element)nodes.item(0);
                headerElement.setPrefix(envelopeElement.getPrefix());
                envelopeElement.appendChild(headerElement);
             }
          }
          else
          {
             System.out.println("Found " + nodes.getLength() + " SOAP Header elements.");
             headerElement = (Element)nodes.item(0);
          }

        /*TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        StreamResult result = new StreamResult(System.out);
        t.transform(source, result);*/

        XMLSignature sig = new XMLSignature(document, "", "http://www.w3.org/2001/04/xmldsig-more#gost34310-gost34311");
        headerElement.appendChild(sig.getElement());
        Transforms transforms = new Transforms(document);
        transforms.addTransform("http://www.w3.org/2000/09/xmldsig#enveloped-signature");
        transforms.addTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments");
        sig.addDocument("", transforms, "http://www.w3.org/2001/04/xmldsig-more#gost34311");
        X509Certificate cert = (X509Certificate) ks.getCertificate("somealias");
        sig.addKeyInfo(cert);
        sig.sign(privateKey);

        StringWriter os = new StringWriter();
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer trans = tf.newTransformer();
        trans.transform(new DOMSource(document), new StreamResult(os));
        os.close();
        System.out.println(os.toString());


        return response;
    }

但它没有工作。它用故障字符串响应soapfault:

java.lang.NullPointerException

谁能证明我做错了什么?我需要将该标志信息添加到响应消息的标题中。

【问题讨论】:

  • @KonstantinV.Salikhov 你读过我写的吗?我不需要那些拦截器,因为它们在 中不包含 之类的标签。和 XWSS 拦截器是一样的!我需要其他解决方案,例如更改响应负载。
  • @bakash_erni 我强烈建议阅读文档以及如何正确配置它。大多数配置显示其他内容的事实并不意味着它不能完成。您需要正确配置安全提供程序。
  • @M.Deinum 无论如何,给我的任务是添加与我上面写的完全相同的标题,而不是其他。我只需要那个标题。
  • 再次阅读文档...

标签: java spring soap response endpoint


【解决方案1】:

好的,我终于用自定义 SmartSoapEndpointInterceptor 解决了这个问题。我创建了实现 SmartSoapEndpointInterceptor 的 MyCustomEndpointInterceptor 并根据我的需要更改了 handleResponse。源代码为:

public class MyCustomEndpointInterceptor implements SmartSoapEndpointInterceptor {

    @Override
    public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
        return true;
    }

    @Override
    public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
        SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
        DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(strMsg);
        Document doc = soapResponse.getDocument();
        // Look for the SOAP header
        Element headerElement = null;
        NodeList nodes = doc.getElementsByTagNameNS("http://schemas.xmlsoap.org/soap/envelope/", "Header");
        if (nodes.getLength() == 0) {
            System.out.println("Adding a SOAP Header Element");
            headerElement = doc.createElementNS("http://schemas.xmlsoap.org/soap/envelope/", "Header");
            nodes = doc.getElementsByTagNameNS("http://schemas.xmlsoap.org/soap/envelope/", "Envelope");
            if (nodes != null) {
                Element envelopeElement = (Element) nodes.item(0);
                headerElement.setPrefix(envelopeElement.getPrefix());
                envelopeElement.appendChild(headerElement);
            }
        } else {
            System.out.println("Found " + nodes.getLength() + " SOAP Header elements.");
            headerElement = (Element) nodes.item(0);
        }

        Provider kncaProvider = new IolaProvider();
        Security.addProvider(kncaProvider);

        KeyStore ks = KeyStore.getInstance("pkcs12", kncaProvider.getName());

        ks.load(new FileInputStream(keypath), keypass.toCharArray());

        PrivateKey privateKey = (PrivateKey) ks.getKey(keyalias, keypass.toCharArray());

        XMLSignature sig = new XMLSignature(doc, "", "http://www.w3.org/2001/04/xmldsig-more#gost34310-gost34311");
        headerElement.appendChild(sig.getElement());
        Transforms transforms = new Transforms(doc); 
        transforms.addTransform("http://www.w3.org/2000/09/xmldsig#enveloped-signature");
        transforms.addTransform("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments");
        sig.addDocument("", transforms,"http://www.w3.org/2001/04/xmldsig-more#gost34311"); 
        X509Certificate cert = (X509Certificate) ks.getCertificate(somealias);
        sig.addKeyInfo(cert); 
        sig.sign(privateKey);

        return true;
    }

    @Override
    public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
        return true;
    }

    @Override
    public boolean shouldIntercept(MessageContext messageContext, Object endpoint) {
        return true;
    }

    @Override
    public boolean understands(SoapHeaderElement header) {
        return true;
    }
}

【讨论】:

    猜你喜欢
    • 2015-04-26
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多