Adding User/Password to SOAPHeader for WebService client call with AXIS2

Adding User/Password to SOAPHeader for WebService client call with AXIS2

Please help: I am trying to call a WebService from SOAPUI and I notice that the service requires username and password which I am providing through the request parameters. I notice that raw XML contains user/password snippet added to SOAPHeader. The snippet is as below:

<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-3" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>testuser</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">testpassword&amp;</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">RYadQak91mr7dB+5hyt8yw==</wsse:Nonce><wsu:Created>2011-10-24T20:13:43.039Z</wsu:Created></wsse:UsernameToken>
</wsse:Security>

Now the same thing I want to achieve by adding user/password details as in the below code: code snippet is:

org.tempuri.myService.MyServiceStub stub = new  org.tempuri.myService.MyServiceStub();

ServiceClient sc = stub._getServiceClient();
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername("testuser");
auth.setPassword("password$");

sc.getOptions().setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE,auth);

org.tempuri.myService.MyServiceDocument myService4 = (org.tempuri.myService.MyServiceDocument)getTestObject(org.tempuri.myService.MyServiceDocument.class);

MyService lval = MyService4.addNewMyService();

MyServiceParameters lvParams = lval.addNewParameters();
lvParams.setA("24");
lvParams.setB("10");

lval.setParameters(lvParams);
myService4.setMyService(lval);

But I get following Axis fault exception, Need help in the mistake I am doing with the above code. Axis Fault Exception details:

org.apache.axis2.AxisFault: Exception occurred while executing service 'MyService'.
    at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:531)
    at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:375)
    at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:421)
    at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
    at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
    at org.tempuri.myService.MyServiceStub.myService(MyServiceStub.java:182)
    at org.tempuri.myService.MyServiceTest.main(MyServiceTest.java:55)

MyServiceResponseDocument lvdoc = stub.myService(myService4);

I resolved the issue myself, this snippet might help some one who want to add additional parameters (atleast this works for me):

The code snippet is as below:

OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMElement omSecurityElement = omFactory.createOMElement(new QName( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "wsse"), null);


OMElement omusertoken = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "UsernameToken", "wsu"), null);

OMElement omuserName = omFactory.createOMElement(new QName("", "Username", "wsse"), null);
omuserName.setText("myusername");

OMElement omPassword = omFactory.createOMElement(new QName("", "Password", "wsse"), null);
omPassword.addAttribute("Type","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",null );
omPassword.setText("mypassword");

omusertoken.addChild(omuserName);
omusertoken.addChild(omPassword);
omSecurityElement.addChild(omusertoken);
stub._getServiceClient().addHeader(omSecurityElement);

Adding Custom Headers Using Client API. Step 1: First you need to get hold of the ServiceClient API. If you are not using generated stubs, then you should use ServiceClient to call the method. But if you are using generated stubs, using Axis2 WSDL2Code mechansim, call _getServiceClient() you can get hold of the ServiceClient.


For anyone else struggling with Invalid Security Header - the answer from Shiv Gopal did not work for me - i received WSS1613: The element UsernameToken inside security header is not supported.

After basically comparing my metro client to my axis2 client and tinkering with every fragment to be 1:1 it boiled down to this:

change

OMElement omusertoken = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "UsernameToken", "wsu"), null);

to

OMElement omusertoken = omFactory.createOMElement(new QName(null, "wsse:UsernameToken", "wsse"), null);

And now authentication works

Hi Sanjoy, Please use AbstractHandler. Write a class extending AbstractHandler and orverride invoke() method. Invoke method will provide you with a provision to get soap envelope and set header in the response.


This dirty code within the Stub class, generated by the axis2:wsdl2code, helped me:

    public void addWsSecurityHeader(String wsUser, String wsPass)
        {

    OMFactory omFactory = OMAbstractFactory.getOMFactory();
    OMElement omSecurityElement = omFactory.createOMElement(new QName( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "wsse"), null);
            omSecurityElement.addAttribute("xmlns:wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-%20wssecurity-utility-1.0.xsd",  null);


    OMElement omusertoken = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "UsernameToken", "wsse"), null);
    omusertoken.addAttribute("wsu:Id","UsernameToken-87",null );

    OMElement omuserName = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd","Username", "wsse"), null);
    omuserName.setText(wsUser);

    OMElement omPassword = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd","Password", "wsse"), null);
    omPassword.addAttribute("Type","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",null );
    omPassword.setText(wsPass);

    omusertoken.addChild(omuserName);
    omusertoken.addChild(omPassword);
    omSecurityElement.addChild(omusertoken);
    this._getServiceClient().addHeader(omSecurityElement);
}

it produced the correct values for the

 ...<wsse:UsernameToken wsu:Id="UsernameToken-87">

aa...

because when the namespaces of the child element coincide with parents' ones, the out put child elements are without it. So you shouldn't use empty namespace for producing tags without it. But i haven't fount how to set several xmlns for the same tag, so I made a dirty hack to create the second xmlns as a tag attribute. May be I was wrong, but it worked.

Usually soap protocol uses http as the transport protocol and hence web service call using soap protocol will have all the freedom to modify any thing related to http transport protocol. Please go through the sample server side and client side codes which I have attached for simple application level authentication using soap.


Adding User/Password to SOAPHeader for WebService client call with AXIS2 at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)


The client calls a web service method called test() but adds a simple SOAP header containing a username and a password. The web service has a BasicHandler, defined in the deployment descriptor as a request handler, which checks each request and makes sure it contains the correct SOAP header with the correct username and password.


For the SAAJ client, two system properties (axis2.repo and axis2.xml) must be set, while for the Axis API, these can be set programmatically (and thus are passed in via command line parameters). The build.xml file shows how to do that for both.