Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: WS-Security UsernameToken Client Side

  1. #1

    Default 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. #2

    Default 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

  3. #3
    Join Date
    Jul 2007
    Posts
    4

    Default

    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

  4. #4

    Default 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

  5. #5
    Join Date
    Jul 2007
    Posts
    4

    Default

    ok if i got the question right this should do :

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

  6. #6

    Default 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.

  7. #7

    Default 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
    		);  
    }

  8. #8

    Default 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;

  9. #9
    Join Date
    Oct 2008
    Posts
    19

    Default

    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

  10. #10
    Join Date
    Oct 2008
    Posts
    19

    Default

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

Posting Permissions

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