Results 1 to 9 of 9

Thread: Problem building a Spring client (Security added with Wss4jSecurityInterceptor)

  1. #1

    Default Problem building a Spring client (Security added with Wss4jSecurityInterceptor)

    Hi,
    I have to write a client Web Service with WS-Security.
    I'm working with J2SDK 1.4, so I chose Wss4jSecurityInterceptor to add security to my client web service code.
    I'm using Spring Web Services 1.5 and the Apache wss4j version distributed with Spring WS, i.e., wss4j 1.5.4

    In the ApplicationContext I have the next configuration:

    Code:
    <bean id="WssClientInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
    		<property name="securementActions" value="UsernameToken"/>
    		<property name="securementMustUnderstand" value="true"/>
    		<property name="securementUsernameTokenElements" value="Nonce Created"/>
    		<property name="securementPasswordType" value="PasswordText"></property>
    		<property name="securementPassword" value="1111"></property>
    		<property name="securementUsername" value="userA"></property>
    	</bean>
    
    <bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    		<property name="interceptors">
    			<list>
    			  <ref bean="WssClientInterceptor"/>
    			</list>
    		</property>
                    .
                    .
    	</bean>
    The interceptor is well passed to the WebServiceTemplate, but when I hope a SOAP Header like this in the outgoing message:

    Code:
    <soapenv:Header>
          <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
             <wsse:UsernameToken wsu:Id="UsernameToken-744817" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
                <wsse:Username>userA</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">1111</wsse:Password>
                <wsse:Nonce>8ucS+F7zhYXs4Fh6u5K/6g==</wsse:Nonce>
                <wsu:Created>2008-11-18T15:03:44.465Z</wsu:Created>
             </wsse:UsernameToken>
          </wsse:Security>
       </soapenv:Header>
    I obtain a SOAP Header like this:

    Code:
    <soapenv:Header>
    		<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="0"/>
    	</soapenv:Header>
    Why am I wrong?

    Thanks a lot.

  2. #2

    Default

    Exactly, the version used to the previous example is Spring-ws-1.5.5

  3. #3

    Default

    Debugging execution code, when Wss4jSecurityInterceptor executes secureMessage method, all seems to be fine until the execution goes to handler.doSenderAction

    Code:
    protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext)
                throws WsSecuritySecurementException {
            if (securementAction == WSConstants.NO_SECURITY && !enableSignatureConfirmation) {
                return;
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Securing message [" + soapMessage + "] with actions [" + securementActions + "]");
            }
            RequestData requestData = initializeRequestData(messageContext);
    
            Document envelopeAsDocument = toDocument(soapMessage, messageContext);
            try {
                // In case on signature confirmation with no other securement
                // action, we need to pass an empty securementActionsVector to avoid
                // NPE
                if (securementAction == WSConstants.NO_SECURITY) {
                    securementActionsVector = new Vector(0);
                }
    
               handler.doSenderAction(securementAction, envelopeAsDocument, requestData, securementActionsVector, false);
            }
            catch (WSSecurityException ex) {
                throw new Wss4jSecuritySecurementException(ex.getMessage(), ex);
            }
    
            replaceMessage(soapMessage, envelopeAsDocument);
        }
    In the envelopeAsDocument variable (it's an Axis SOAPPart type), I can see in the currentMessage (it's a SOAPEnvelope type) variable the next value:

    Code:
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="0"/></soapenv:Header><soapenv:Body><ns1:changeUserPassword xmlns:ns1="urn:OPI"><ns1:newPassword>11</ns1:newPassword><ns1:userName>juanjo</ns1:userName></ns1:changeUserPassword></soapenv:Body></soapenv:Envelope>
    Then, I suppose the code doesn't work correctly is the handler method doSenderAction, isn't it?

    Obviusly, the handler (WssjHandler, that delegates in org.apache.ws.security.handler.WSHandler) is not part of the Spring package, but

    someone has been the same problem as I do?

  4. #4

    Default

    I continue with this strange behaviour.

    More clues:

    When the execution arrives at the Apache WSHandler class (this class is in wss4j-1.5.4.jar), has the next variable values:

    doAction = 1 (int)

    so, in the doSenderAction method of WSHandler

    Code:
     if ((doAction & WSConstants.UT) == WSConstants.UT) {
                decodeUTParameter(reqData);
            }
    it should go through the decodeUTParameter method (WSConstants.UT is 1).
    But, if I put a debug breakpoint in the decodeUTParameter method, the execution doesn't stop there.

    Nevertheless, I'm using Eclipse 3.2 as IDE and when I stop the execution in the wss4j code, it's strange beacuse I do the typical step by step execution (in Eclipse is with F6 key) and the code doesn't correspond with the runtime execution. I don't know if there is some known trouble with the version of wss4j, beacuse I've tried everything. I've used the jar that comes with Spring distribution, also I've used the jar directly downloaded from wss4j web page, I've downloaded the source code of that version (1.5.4) and I always have the same result.

    I'm desesperately confused.

  5. #5

    Default

    Finally, I've discovered there is a bug in wss4j.

    Debugging the code, I've found that WSHandler, for my purpose, mainly uses two other classes: WSSecUsernameToken and WSSecurityUtil. The last one is intended to work with DOM objects and SOAP Security Headers.

    The code execution flow is:

    WSSecUsernameToken
    Code:
    public Document build(Document doc, WSSecHeader secHeader) {
    		log.debug("Begin add username token...");
    
    		prepare(doc);
    		prependToHeader(secHeader);
    		
    		return doc;
    	}
    and prependToHeader method calls:

    Code:
    WSSecurityUtil.prependChildElement(document, secHeader.getSecurityHeader(), ut.getElement(), false);
    and then, the WSSecurityUtil.prependChildElement code is:
    Code:
    public static Element prependChildElement(Document doc, Element parent,
                Element child, boolean addWhitespace) {
            Node firstChild = parent.getFirstChild();
            if (firstChild == null) {
                parent.appendChild(child);
            } else {
                parent.insertBefore(child, firstChild);
            }
            if (addWhitespace) {
                Node whitespaceText = doc.createTextNode("\n");
                parent.insertBefore(whitespaceText, child);
            }
            return child;
        }
    In the execution, the doc is the SOAPMessage, the parent is the SecurityHeader DOM element and the child is the UserNameToken DOM element.
    It's a bit difficult, but if you pay attention to the execution, there's a separation of concerns between the WSSecHeader passed to UserNameTokenAction and the doc that represents the SOAP message. So, although the last method builds a good security DOM element

    Code:
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    	<wsse:UsernameToken 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" wsu:Id="UsernameToken-5764479">
    		<wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">userName</wsse:Username>
    		<wsse:Password xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">1111</wsse:Password>
    		<wsse:Nonce xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">uzL0ydaZc0vcdN3WoQxSzw==</wsse:Nonce>
    		<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2008-12-10T17:33:08.750Z</wsu:Created>
    	</wsse:UsernameToken>
    </wsse:Security>
    the document (the SOAP Message) doesn't refresh its Security header, because those objects are different and disconnected.

    So, finally, it's a wss4j bug.

    I change my wss4j code to resolve the use case, but I think it's not a general purpose solution, so I prefer not to mention it here.

    What's the policy when someone find a bug in another system (wss4j in this case), and it affects the features of Spring? (In the Spring reference, you offer the feature as if it works)

  6. #6

    Default

    Hi,

    First of all thanks a lot for sharing your findings and progress through out this issue.
    If you are sure that you found a genuine Wss4j bug, then you should raise an issue on Wss4j's issue tracker. You can also ask for help on their mailing list.
    I have to admit I'm a bit confused though. What you're trying to achieve is pretty basic (Username Token with some sub elements) and should work flawlessly. I failed to notice anything wrong in your configuration.
    I would like to take a closer look. Do you have any test code that reproduces the problem to share? That would be great.
    Tareq Abedrabbo

    My Twitter
    My Blog

  7. #7

    Default xmlsec jar downgrade

    jjmargon - If you are using xmlsec-1.4.1.jar on your classpath, try replacing xmlsec-1.4.1.jar with the previous release - xmlsec-1.4.0.jar which is shipped in the with-dependencies release of spring-ws 1.5.4 (previous release). I ran into a bug in xmlsec 1.4.1 when using wss4j with spring-ws, but downgrading to xmlsec 1.4.0 fixed my problem, so you may want to give it a try. The bug I ran into is described here: http://jira.springframework.org/browse/SWS-447. Hope this helps.

  8. #8

    Default

    Hi, pdotsenko
    I've tried both versions of xmlsec and the result is the same.
    I think it's a mistake of wss4j code.
    Thanks

  9. #9

    Default

    Hi, tareq.
    This example took place in a real project and unfortunately, this is not a very good environment and we don't work with test cases. Bad practice in any case. I'm "fighting" to change this situation, but the history of company's practice doesn't help me a lot.
    In any case, I'll work on a test case at the weekend and I'll share the results with you.
    I agree with you that my case is one of the most simple WS-Security posibilities (UsernameToken with PasswordText), and I was surprised with the result.
    Thanks a lot.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •