web-servicessoap-clientws-securitysoapheaderjava-ws

How to Iterate all Child Element SOAP Headers as per the below web service client


Basically I am trying to write the JAX-WS service side code as per the article link below.

Code in handleMessage for web service client ( complete code is in http://informatictips.blogspot.com/2013/09/using-message-handler-to-alter-soap.html )

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("TestUser");
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#PasswordText");
password.addTextNode("TestPassword"); ```

Now how to write relevant server side code for below input soap xml

 <s:header>
  <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>TestUser</wsse:username>
            <wsse:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPassword</wsse:password>
       </wsse:usernametoken>
  </wsse:security>
</s:header>

Solution

  • I am able to write the code for server side handler code for validating the WebService -Security Headers for OASIS, PFB handlerMessage(.) method looks like.

    Input XML

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
      <SOAP-ENV:Header>
         <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 >TestUser</wsse:username>
                   <wsse:password type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPassword</wsse:password>
              </wsse:usernametoken>
         </wsse:security>
    </SOAP-ENV:Header>
       <S:Body>
          <ns2:getAreaDeatilsByPinCode xmlns:ns2="http://contract.webservice.room/">
             <arg0>12</arg0>
          </ns2:getAreaDeatilsByPinCode>
       </S:Body>
    </S:Envelope>
    
    
    @Override
        public boolean handleMessage(SOAPMessageContext soapMessageContext) {
    
            // WS-Security - Publisher - OASIS,  Namespace URI 
            final String WSSE_NS_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
            // Qualifier with header elements 
            final QName QNAME_WSSE_USERNAMETOKEN = new QName(WSSE_NS_URI, "usernametoken");
            final QName QNAME_WSSE_USERNAME = new QName(WSSE_NS_URI, "username");
            final QName QNAME_WSSE_PASSWORD = new QName(WSSE_NS_URI, "password");
    
            String wsseUsername = null;
            String wssePassword = null;
    
            System.out.println("Handler trigger for " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            Boolean isRequest = (Boolean) soapMessageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            if (!isRequest) {
                try {
    
                    SOAPHeader header = soapMessageContext.getMessage().getSOAPHeader();
                    if (header == null) {
                        header = soapMessageContext.getMessage().getSOAPPart().getEnvelope().addHeader();
                        generateSOAPErrMessage(soapMessageContext.getMessage(), "No SOA Header");
                    }
                    // Get client data from SOAP headers
                    Iterator<?> headerElements = header.examineAllHeaderElements();
                    while (headerElements.hasNext()) {
                        SOAPHeaderElement headerElement = (SOAPHeaderElement) headerElements.next();
                        if (headerElement.getElementName().getLocalName().equals("security")) {
                            System.out.println("inside security");
                            SOAPHeaderElement securityElement = headerElement;
                            Iterator<?> securityChildern = securityElement.getChildElements();
                            while (securityChildern.hasNext()) {
                                System.out.println("inside securityChildern");
                                Node node = (Node) securityChildern.next();
                                if (node instanceof SOAPElement) {
                                    System.out.println("insdie node...");
                                    SOAPElement element = (SOAPElement) node;
                                    QName elementQname = element.getElementQName();
                                    if (QNAME_WSSE_USERNAMETOKEN.equals(elementQname)) {
    
                                        System.out.println("validating username and password...");
                                        SOAPElement usernameTokenElement = element;
                                        wsseUsername = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_USERNAME);
                                        wssePassword = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_PASSWORD);
                                        if(!wsseUsername.equals("TestUser") || !wssePassword.equals("TestPassword")){
                                            generateSOAPErrMessage(soapMessageContext.getMessage(), "username and password are wrong....");
                                        }
                                        System.out.println("username::"+wsseUsername+ " , password::"+wssePassword);
                                        break;
                                    }
                                }
                            }
                            if (wsseUsername != null) {
                                break;
                            }
                        }
                    }
    
                } catch (SOAPException e) {
                    e.printStackTrace();
                }
            }
            return true;
        }
    
        private String getFirstChildElementValue(SOAPElement usernameTokenElement, QName qNAME_WSSE_USERNAME) {
    
            System.out.println("get username and password");
            String value = null;
            Iterator<?> usernameTokenChilderen = usernameTokenElement.getChildElements(qNAME_WSSE_USERNAME);
    
            while (usernameTokenChilderen.hasNext()) {
                System.out.println("get the child elment for username and password");
                SOAPElement childElement = (SOAPElement) usernameTokenChilderen.next();
                value = childElement.getValue();
            }
    
            return value;
        }
    
        private void generateSOAPErrMessage(SOAPMessage message, String cause) {
    
            try {
                SOAPBody faultBody = message.getSOAPPart().getEnvelope().getBody();
    
                SOAPFault soapFault = faultBody.addFault();
                soapFault.setFaultString(cause);
                throw new SOAPFaultException(soapFault);
    
            } catch (SOAPException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
    
    

    Valid request

    
        <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
           <S:Body>
              <ns2:getAreaDeatilsByPinCodeResponse xmlns:ns2="http://contract.webservice.room/">
                 <return>
                    <areaName>XXXXX</areaName>
                    <location>XXXXX</location>
                    <pincode>12</pincode>
                    <state>XX</state>
                 </return>
              </ns2:getAreaDeatilsByPinCodeResponse>
           </S:Body>
        </S:Envelope>
    
    

    Unauthorized Request

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
       <S:Body>
          <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
             <faultcode>S:Server</faultcode>
             <faultstring>username and password are wrong....</faultstring>
          </S:Fault>
       </S:Body>
    </S:Envelope>