We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

How to add security header to SOAP webservice client on java

Medium Priority
17,937 Views
Last Modified: 2013-11-23
Greetings to all,

I have been developing a Client in netbeans 6.7.1 for a web service using Oasis UsernameToken security, I managed to create the client and the classes from the tool and  the consumer method goes like this


and returns the following Exception:

Error: javax.xml.ws.soap.SOAPFaultException: Security requirements are not satisfied because the security header is not present in the incoming message


I found an example on how to create a Header Handler and I implemented it, but for some reason the function is not called properly and fails to attach the header.


The header has to be something like this:



So my questions are:

Does anybody know a way to successfully append a security header to an outgoing SOAP request?

is there an interface for doing such thing? (in my research i found that a plugin for Glassfish called Access Manager that did all this handling,  but it has been removed for some reason)

What is the proper way to develop a Webservice Client with UsernameToken authentication?

Thanks in advance



<wsse:Security xmlns:wsse=$\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd$\">" +
                <wsse:UsernameToken xmlns:wsu=$\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd$\">" +
                      <wsse:Username>" + user + "</wsse:Username>" +
                      <wsse:Password Type=$\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest$\">password</wsse:Password>" +
                      <wsse:Nonce>" + noncepack + "</wsse:Nonce>" +
                      <wsu:Created>" + sdf.format(c1.getTime()) + "</wsu:Created>" +
              </wsse:UsernameToken>" +
          </wsse:Security>"

Open in new window

try { // Call Web Service Operation
            xxxxxx.Service service = new xxxxxxx.Service();

            xxxxx.ServiceSoap port = service.getServiceSoap();
            // TODO initialize WS operation arguments here
            java.lang.String subscriberID = "ClientID";
            java.lang.String identity = "Client Identity";
            // TODO process result here
            xxxxxxx.SubscriberRetrieve result = port.retrieveSubscriber(subscriberID, identity);
            info("Result = " + result);
        } catch (Exception ex) {
            error("Error: " + ex);
            // TODO handle custom exceptions here
        }

Open in new window

Comment
Watch Question

Siva Prasanna KumarPrincipal Solutions Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
/*

* This is where you can add your custom SOAP headers if required.

* Example: WS-Security Username token etc, below shown is a custom

* Authentication header(not required for this service). just added

* for example

*/

SOAPHeader soapHeader = soapMessage.getSOAPHeader();

Name userName = soapEnvelope.createName("username", "",

"http://MyUserCredentials");

SOAPHeaderElement userNameElement = soapHeader

.addHeaderElement(userName);

userNameElement.setValue("SHIVA");

Name password = soapEnvelope.createName("password", "",

"http://MyUserCredentials");

SOAPHeaderElement passwordElement = soapHeader

.addHeaderElement(password);

passwordElement.setValue("OMMMMMMMMMMM");

//Constructing SOAP Body.

SOAPBody soapBody = soapMessage.getSOAPBody();

Open in new window


This is a snippet from my blog, complete article here : http://soa2world.blogspot.com/2009/05/direct-web-service-client-using-java.html

Author

Commented:
thanks shivaspk for your answer, I just want to ask a couple of questions more, that works for a password digest with nonce and timestamp? and once the hearder is create how do I append it to the outgoing SOAP message that JAX-WS sends?

Namaste
Siva Prasanna KumarPrincipal Solutions Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
You can do it as shown here: http://www.java.net/node/712962

Ya this approach can work for both nonce and timestamp. A nonce is a random value that the sender creates to include in each UsernameToken that it sends. A creation time is added to combine nonces to a "freshness" time period.

Author

Commented:
ok I'm trying to implement the second link you provided me, if successful I give you the points, thank you so much for the response

Author

Commented:
I have come to something like this
try { // Call Web Service Operation
            com.comverse_in.prepaid.ccws.Service service = 
            new com.comverse_in.prepaid.ccws.Service();
            com.comverse_in.prepaid.ccws.ServiceSoap port = service.getServiceSoap();
//             TODO initialize WS operation arguments here
            WSBindingProvider bp = (WSBindingProvider) port;
            SOAPMessage message = null;
            message = javax.xml.soap.MessageFactory.newInstance().createMessage();
            SOAPHeader header = message.getSOAPHeader();
            SOAPElement security =
                    header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

            SOAPElement usernameToken =
                    security.addChildElement("UsernameToken", "wsse");
            usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

            SOAPElement username =
                    usernameToken.addChildElement("Username", "wsse");
            username.addTextNode("USERNAME");

            SOAPElement password =
                    usernameToken.addChildElement("Password", "wsse");
            password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
            //setting up the password Digest
            String unique = UniqId.getInstance().getUniqID();
            BASE64Encoder encoder = new BASE64Encoder();
            String NotEvenOnce = encoder.encode(unique.getBytes());
            //2011-04-05T19:51:46Z Format timestamp 'Y-m-d\TH:i:s\Z'
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            Calendar c1 = Calendar.getInstance();
            c1.add(Calendar.HOUR_OF_DAY, 6);
            String creaDate = sdf.format(c1.getTime());
            String Hash = hash;
            try {
                 Hash = getHash(NotEvenOnce + creaDate + "C@pt1v0");
            } catch (NoSuchAlgorithmException ex) {
                error("hash error " + ex);
            }

            // PACKING
            byte[] b = new BigInteger(Hash, 16).toByteArray(); //maybe other
//        constructor to implement other formats of pack()
            String pack = new String(b, "UTF-8").substring(1); //first char is sign
            String PassDigest = encoder.encode(pack.getBytes());
            password.addTextNode(PassDigest);

            SOAPElement nonce =
                    usernameToken.addChildElement("Nonce", "wsse");
//                        nonce.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
            nonce.addTextNode(NotEvenOnce);

            SOAPElement created =
                    usernameToken.addChildElement("Created", "wsu");
            created.addTextNode(creaDate);

            //SOAP HEADER Building finished

            bp.setOutboundHeaders(header);


            java.lang.String subscriberID = "phoneNo";
            java.lang.String identity = "Id";
//             TODO process result here
            com.comverse_in.prepaid.ccws.SubscriberRetrieveLite result = port.retrieveSubscriberLite(subscriberID, identity);
            info("Result = " + result.getBalance());
            try {
                handleMessage((SOAPMessageContext) message);
            } catch (Exception e) {
                info("Excepcion " + e);
            }

        } catch (Exception ex) {
            error("Error calling the WebService: " + ex);
        }

Open in new window

Based on the second example given, and that gives me the following error.

javax.xml.ws.WebServiceException: com.sun.istack.XMLStreamException2: javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.SAXException2: unable to marshal type "com.sun.xml.messaging.saaj.soap.ver1_1.Header1_1Impl" as an element because it is missing an @XmlRootElement annotation]

What at this time I don't undestand
Siva Prasanna KumarPrincipal Solutions Architect
CERTIFIED EXPERT
Top Expert 2006

Commented:
What JAX-WS Engine are you using?, Axis2 or Metro? Let me know I will try out a example and provide the actual solution.

Author

Commented:
Thank you Shivaspk, the server I'm using is Apache Tomcat, so I take the guess that is axis the engine. I have been battling with this issue for a while

very much appreciated.
Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview

Author

Commented:
because no one else had an answer and I found it by myself

Commented:
hi, can you please let us know how did you implement this. I have similar requirement, your solution can help me.
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.