Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8186441

Change of behavior in the getMessage () method of the SOAPMessageContextImpl class

XMLWordPrintable

    • b35
    • x86_64
    • windows_7

        FULL PRODUCT VERSION :
        java version "1.8.0_144"
        Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
        Java HotSpot(TM) Client VM (build 25.144-b01, mixed mode, sharing)


        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Versión 6.1.7601]

        A DESCRIPTION OF THE PROBLEM :

        Using the default implementation of jaxws and xml api distributed with the jre Java(TM) SE Runtime Environment (build 1.8.0_141-b15)

        In a web service client jaxws which has a handler that implements SOAPHandler<SOAPMessageContext>, used to sing the payload inside the SOAP Message, since 1.8.0_141-b15 version, the message obtained with the getMessage() method of the com.sun.xml.internal.ws.handler.SOAPMessageContextImp class, to be signed moves the namespaces of the root tag of the payload to the Soap Body tag, and then signs a String xml different from the original sent by user.

        Besides, when deleting the namespace from the root tag of the payload of the Soap Message, causes the server does not know which operation is responsible for processing that message for not bearing the namespace.

        The same problem occurs with the response, when is used the SOAPMessageContextImpl .getMessage() to obtain the SOAPMEssage, then it moves the namespaces and check the signature. It always fails because we are not checking the original message which answers the server.

        Activating java debugging we can see clearly:

        ---[HTTP response - https://host/ServiceContext/ServiceEME - 200]---
        Connection: Keep-Alive
        Content-Type: application/soap+xml; charset=utf-8
        Date: Wed, 09 Aug 2017 17:09:51 GMT
        Keep-Alive: timeout=5, max=100
        Referrer-policy: no-referrer
        Server: MSX-2
        Set-Cookie: _WL_AUTHCOOKIE_JSESSIONID=5iLt2F1sTk9G08vAd2qc; path=/; secure; ; Secure; HttpOnly
        Strict-Transport-Security: max-age=63072000;
        Transfer-Encoding: chunked
        X-Frame-Options: SAMEORIGIN
        X-XSS-Protection: 1; mode=block
        <?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
        <SOAP-ENV:Body>
        <ResponseMessage xmlns="http://iec.ch/TC57/2011/schema/message"><Header><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:09:02.359Z</Timestamp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI=""><Tran


        In the client response Handler when the message is obtained by this method is different from the original message sent by the server.

        @Override
            public boolean handleMessage(final SOAPMessageContext messageContext) {

                SOAPMessage message = messageContext.context.getMessage()
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                message.writeTo(baos);
                String soapToSing= baos.toString(StandardCharsets.UTF_8.name());

        }


        The soapToSing has the next content:

        <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Header/
        ><SOAP-ENV:Body xmlns="http://iec.ch/TC57/2011/schema/message"><ResponseMessage><Header xmlns="http://iec.ch/TC57/2011/schema/message"><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:0

        The namesapace of the RequestMessage has no namespace and it has been transferred to the Body tag.


        REGRESSION. Last worked in version 8u131

        ADDITIONAL REGRESSION INFORMATION:
        Java(TM) SE Runtime Environment (build 1.8.0_131-b11)

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The string extracted from the SoapMessageContext should be:


        <SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
        <SOAP-ENV:Body>
        <ResponseMessage xmlns="http://iec.ch/TC57/2011/schema/message"><Header><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:09:02.359Z</Timestamp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI=""><Tran..........

        ACTUAL -
        The string extracted from the SoapMessageContext is:


        <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Header/
        ><SOAP-ENV:Body xmlns="http://iec.ch/TC57/2011/schema/message"><ResponseMessage><Header xmlns="http://iec.ch/TC57/2011/schema/message"><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:0

        The Body has the namespace of the RequestMessage tag, and the RequestMessage needs the namespace to be processed by the webservice in the server.


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        A webservice client uses the default implemenattion of jaxws ot the jre distribution.

        Client code where the handler is attached ...

        @SuppressWarnings("rawtypes")
            protected final ResponseMessage sendMessage(final RequestMessage message) throws HandlerException {

                ResponseMessage retValue = null;

                try {
                    ServiceEME service = new ServiceEME(getClass().getClassLoader().getResource(WSDL_FILE), SERVICE_NAME);
                    PortTFEDIType port = service.getServiceEMEPort();
                    BindingProvider bindingProvider = (BindingProvider) port;
                    bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint.toString());

                    /* sets a handler in order to sign and verify signature. The handler is useful also for debug. */
                    messageMetaData = new MessageMetaData();
                    Binding binding = bindingProvider.getBinding();
                    List<Handler> handlerList = binding.getHandlerChain();
                    handlerList.add(new SendHandler(signRequest, verifyResponse, messageMetaData, certificate, privateKey));
                    binding.setHandlerChain(handlerList);

                    retValue = port.request(message);

                    /* Throws exception if the retrieved message has an invalid signature. */
                    MessageMetaData metadata = getMessageMetaData();
                    if (metadata.getException() != null) {
                        throw (HandlerException) metadata.getException();
                    }

                } catch (MsgFaultMsg ex) {


        -- Code of the Handler SendHandler.java used in request and response of a webservice call.
        public final class SendHandler implements SOAPHandler<SOAPMessageContext> {


            public SendHandler() {
            }

            /**
             * Gets this handler headers.
             * @return An empty set.
             */
            @Override
            public Set<QName> getHeaders() {

                return Collections.emptySet();
            }

            /**
             * Called at the end of a message interchange.
             * @param mc Message context.
             */
            @Override
            public void close(final MessageContext mc) {

                /* This method should not be implemented. */
            }


            @Override
            public boolean handleFault(final SOAPMessageContext messageContext) {

               return true;
            }


            @Override
            public boolean handleMessage(final SOAPMessageContext messageContext) {


                SOAPMessage message = messageContext.context.getMessage()
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                message.writeTo(baos);
                String soapToSing= baos.toString(StandardCharsets.UTF_8.name());

        /**THE SOAPTOSING is different from the original*/

        ............
                return true;
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Force the classpath of the client to use an older implementation for jax-ws,
        We have used next implementation:
            <dependency>
              <groupId>com.sun.xml.ws</groupId>
              <artifactId>jaxws-rt</artifactId>
            <version>2.2.6</version>


              aefimov Aleksej Efimov
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: