Announcement Announcement Module
Collapse
No announcement yet.
WS-Security UsernameToken Client Side Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • WS-Security UsernameToken Client Side

    I am using the AcegiPlainTextPasswordValidationCallbackHandler on the server side to authenticate web services using WS-Security. I am at a point where I need to do some initial testing and I want to write a simple Java Client to test my web services. I was looking at using WebServiceTemplate, but it isn't clear to me how I go about setting the username and password so that the required WS-Security is added to the resulting SOAP message.

    What is the recommended method for implementing WS-Security authentication on the client side? Do I need to use a callback to add the raw header myself or is there a cleaner way to do it? If I have to add the raw header, does anyone have an example of this that might help me avoid a lot of trial and error getting the header contents right?

    Thanks.

    Bill

  • #2
    How to set a header

    In the interim, while waiting for an answer, I decided to dig into the javadocs and see what it would take to set the header myself on the client.

    I was surprised to find that there is no method for adding a header to the message. There are methods for getting the headers and for setting a SOAP action header, but I don't see any support for adding headers.

    What am I missing? What point is there in supporting WS-Security on the server side if there is no way to add the required headers on the client side?

    Surely there must be a way and I'm just overlooking it, right?

    Bill

    Comment


    • #3
      hello,

      you can add the soapaction header by passing a webservicecallback while you are sending the soap message( ex: marshallsendandreceive) and in the callback you can cast the webservicemessage parameter like this:

      SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
      SOAPMessage saajMessage = saajSoapMessage.getSaajMessage();

      //and add the soapactionheader

      saajSoapMessage
      .setSoapAction("soapAction string");

      hope this is useful
      soloist

      Comment


      • #4
        Adding Headers

        Thanks, but I don't think this is what I need. I saw that method, too, but when I read the javadoc it seems that this can be used to set the SOAP action only. It cannot be used to add arbitrary other headers like those used by WS-Security. The UsernameToken header does not just contain a simple string, but includes numerous other XML elements. What would I pass as the parameter? Also, since the examples all pass a string containing no XML markup, I assume the method must add some XML markup what is passed ... markup I probably don' t want to be part of my header ... or at least markup I would need to know about if I am to omit it from the string I pass a parameter.

        Bill

        Comment


        • #5
          ok if i got the question right this should do :

          http://www.jroller.com/0xcafebabe/en...s_client_with1

          Comment


          • #6
            Thanks

            Yep. I think this is what I was looking for. I searched high and low and never stumbled across this article somehow. I think this will do what I need for the purposes of testing. There is one thing about it that bugs me a little from a deployment perspective. It seems to require that you put the username and password in a configuration file. Not only does this seem a bit unrealistic, but also a bit hinky from a security perspective. I haven't looked at the XWSS API yet though so it may be possible to set username and password in code.

            Thanks again for the help.

            Comment


            • #7
              Maybe this helps

              Hey,

              You can use this implementation of WebServiceMessageCallback in order
              to inject a WS-Security compliant SOAP header (including userName and password) into your request using a Spring-WS client.
              (btw this may be a fit for org.springframework.ws.client.support)

              Code:
              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);
              		}
              	}
              }
              the Spring-WS client can do this:

              Code:
              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
              		);  
              }

              Comment


              • #8
                import statements for WSSESecurityHeaderRequestWebServiceMessageCallback

                import java.io.IOException;

                import javax.xml.soap.Name;
                import javax.xml.soap.SOAPElement;
                import javax.xml.soap.SOAPEnvelope;
                import javax.xml.soap.SOAPException;
                import javax.xml.soap.SOAPHeader;
                import javax.xml.soap.SOAPHeaderElement;
                import javax.xml.soap.SOAPMessage;
                import javax.xml.soap.SOAPPart;
                import javax.xml.transform.TransformerException;

                import org.springframework.ws.WebServiceMessage;
                import org.springframework.ws.client.core.WebServiceMessa geCallback;
                import org.springframework.ws.soap.saaj.SaajSoapMessage;

                Comment


                • #9
                  I used the code above to create the UsernameToken by hand, but I am getting the following error.

                  Code:
                   org.springframework.ws.soap.client.SoapFaultClientException: Security processing failed (actions mismatch)
                  This is my configuration
                  Code:
                  		<bean id="wss4jSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
                  		  <property name="validationActions" value="UsernameToken"/>
                  		   <property name="validationCallbackHandler">
                  			  <bean id="springSecurityHandler"
                  			      class="org.springframework.ws.soap.security.wss4j.callback.SpringPlainTextPasswordValidationCallbackHandler">
                  			    <property name="authenticationManager" ref="authenticationManager"/>
                  			  </bean>
                  		   </property>
                  		</bean>

                  Any help would be great. thanks

                  Comment


                  • #10
                    Adding the namespace to each of the UsernameToken elements solved the problem for me.

                    Ex:
                    Code:
                     SOAPElement userNameSOAPElement = usernameTokenSOAPElement
                    	                    .addChildElement(WSSE_Username_Elem,WSSE_Security_prefix, WSS_10_NAMESPACE);

                    Comment


                    • #11
                      Wss4jSecurityInterceptor and XwsSecurityInterceptor implement ClientInterceptor. It means that they can be used on the client side as well.

                      Comment


                      • #12
                        Thanks a lot Horst for providing the code snippet that can be used for WSSecurity CallBack.

                        Comment

                        Working...
                        X