javaweb-servicessoapjax-ws

Retrieving Soap Header on JAXWS Server Side


We are trying to do a security implementation in our JAX web services and are passing the UserName and Password in the header as below.

<soapenv:Header>
    <wsse:Security soapenv:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <wsse:UsernameToken wsu:Id="Id-8zvykuwmK8yg6dxn3632nQJB" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:Username>gears_user</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">##########</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>

In the Java we are trying the retrieve the Username and the password but we are not sure how to do it as, its a part of Soap Header and we have not retrieved header information before.

    .....
     @Resource
WebServiceContext wsctx;


public ServiceAvailabilityResponseType inquireGeographicEligibility(ServiceAvailabilityRequestType inquireGeographicEligibilityRequest)
    throws WSException
{

     HeaderList hl=(HeaderList)wsctx.getMessageContext().get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);
     QName security = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", 
            "Security");    
     Header hd = hl.get(security, false);


     QName userName = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", 
        "Username");
     try
     {
         System.out.println(hd.readHeader());    
         System.out.println(hd.getAttribute(userName));
     }catch (Exception e) {
        System.out.println(e.getMessage());
    }

   }

We are trying to do as above and get the header elements but its not returning us the value. Any help on the way to retrieve the Username and Password will be appreciated.


Solution

  • You can read the soap header from the SOAPMessageContext in a SOAPHandler class, then pass the values to your @WebService implementation via attributes in the MessageContext.

    Whereas the HeaderList API is specific to the JAX-WS reference implementation, the following sample should be portable across any JAX-WS runtime.

    Example:

    Web service impl:

    package org.example.sampleservice;
    
    import javax.annotation.Resource;
    import javax.jws.HandlerChain;
    import javax.jws.WebService;
    import javax.xml.ws.WebServiceContext;
    
    @WebService(endpointInterface = "org.example.sampleservice.SampleService")
    @HandlerChain(file="handlers.xml")
    public class SampleServiceImpl implements SampleService {
    
        @Resource
        private WebServiceContext ctx;
    
        @Override
        public String sayHello(String name) {
            String usernameFromHeader = (String) ctx.getMessageContext().get("USERNAME");
            return "Hello, "
                    + name
                    + " (invoked by "
                    + (usernameFromHeader == null ? "[err or no 'Security' header found]"
                            : usernameFromHeader) + ")";
        }
    
    }
    

    Handler chain XML (handlers.xml, a file in the same package as SampleServiceImpl.java):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <javaee:handler-chains 
         xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <javaee:handler-chain>
        <javaee:handler>
          <javaee:handler-class>org.example.sampleservice.UsernameTokenHandler</javaee:handler-class>
        </javaee:handler>
      </javaee:handler-chain>
    </javaee:handler-chains>
    

    The JAX-WS handler class:

    package org.example.sampleservice;
    
    import java.util.Iterator;
    import java.util.Set;
    
    import javax.xml.namespace.QName;
    import javax.xml.soap.Node;
    import javax.xml.soap.SOAPElement;
    import javax.xml.soap.SOAPHeader;
    import javax.xml.soap.SOAPHeaderElement;
    import javax.xml.ws.handler.MessageContext;
    import javax.xml.ws.handler.MessageContext.Scope;
    import javax.xml.ws.handler.soap.SOAPHandler;
    import javax.xml.ws.handler.soap.SOAPMessageContext;
    
    public class UsernameTokenHandler implements SOAPHandler<SOAPMessageContext> {
    
        private static final String WSSE_NS_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
        private static final QName QNAME_WSSE_USERNAMETOKEN = new QName(WSSE_NS_URI, "UsernameToken");
        private static final QName QNAME_WSSE_USERNAME = new QName(WSSE_NS_URI, "Username");
        private static final QName QNAME_WSSE_PASSWORD = new QName(WSSE_NS_URI, "Password");
    
        @Override
        public boolean handleMessage(SOAPMessageContext context) {
    
            Boolean outbound = (Boolean) context
                    .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            if ((outbound != null) && (!outbound.booleanValue())) {
                handleInboundMessage(context);
            }
            return true;
        }
    
        private void handleInboundMessage(SOAPMessageContext context) {
            String wsseUsername = null;
            String wssePassword = null;
            try {
                SOAPHeader header = context.getMessage().getSOAPHeader();
                Iterator<?> headerElements = header.examineAllHeaderElements();
                while (headerElements.hasNext()) {
                    SOAPHeaderElement headerElement = (SOAPHeaderElement) headerElements
                            .next();
                    if (headerElement.getElementName().getLocalName()
                            .equals("Security")) {
                        SOAPHeaderElement securityElement = headerElement;
                        Iterator<?> it2 = securityElement.getChildElements();
                        while (it2.hasNext()) {
                            Node soapNode = (Node) it2.next();
                            if (soapNode instanceof SOAPElement) {
                                SOAPElement element = (SOAPElement) soapNode;
                                QName elementQname = element.getElementQName();
                                if (QNAME_WSSE_USERNAMETOKEN.equals(elementQname)) {
                                    SOAPElement usernameTokenElement = element;
                                    wsseUsername = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_USERNAME);
                                    wssePassword = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_PASSWORD);
                                    break;
                                }
                            }
    
                            if (wsseUsername != null) {
                                break;
                            }
                        }
                    }
                    context.put("USERNAME", wsseUsername);
                    context.setScope("USERNAME", Scope.APPLICATION);
    
                    context.put("PASSWORD", wssePassword);
                    context.setScope("PASSWORD", Scope.APPLICATION);
                }
            } catch (Exception e) {
                System.out.println("Error reading SOAP message context: " + e);
                e.printStackTrace();
            }
    
        }
    
        private String getFirstChildElementValue(SOAPElement soapElement, QName qNameToFind) {
            String value = null;
            Iterator<?> it = soapElement.getChildElements(qNameToFind);
            while (it.hasNext()) {
                SOAPElement element = (SOAPElement) it.next(); //use first
                value = element.getValue();
            }
            return value;
        }
    
        @Override
        public boolean handleFault(SOAPMessageContext context) {
            return false;
        }
    
        @Override
        public void close(MessageContext context) {
        }
    
    
        @Override
        public Set<QName> getHeaders() {
            return null;
        }
    
    }