Wednesday 27 July 2016

Add security header into soap request(Spring jax-ws)

Purpose of this note is to showcase adding security information like below into message header

    <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
       <S:Header>
          <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
             <wsse:UsernameToken>
                <wsse:Username>XXXXX</wsse:Username>
                <wsse:Password>XXX@mCC</wsse:Password>
             </wsse:UsernameToken>
          </wsse:Security>
       </S:Header>
       <S:Body>
    


     <bean id="aomWSHandlerResolver" class="xx.webservice.util.DefaultHandlerResolver">
        <property name="handlers">
          <list>
             <bean class="xx.webservice.util.SecurityHandler"/>
          </list>
        </property>
      </bean>





<bean id="aomWebServiceProxyParent" abstract="true" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
    <property name="namespaceUri" value="http://xx.xx.com/services"/>
    <property name="serviceName" value="ApiService"/>
    <property name="lookupServiceOnStartup" value="false"/>
     <property name="handlerResolver" ref="aomWSHandlerResolver"/>
     <property name="username" value="xx"/>
    <property name="password" value="xx"/>
    <property name="customProperties">
      <map key-type="java.lang.String" value-type="java.lang.Integer">
        <entry key="com.sun.xml.ws.connect.timeout" value="${webservice.connect.timeout.millisec}"/>
        <entry key="com.sun.xml.ws.request.timeout" value="${webservice.response.timeout.millisec}"/>
      </map>
    </property>
   
  </bean>
 

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
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.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * Handler that logs all the SOAP requests/responses using SL4J.
 *
 */
public final class SecurityHandler extends SoapHandler {

    
   
    /**
     * Logger.
     */
    private static final Logger logger = LoggerFactory.getLogger(SecurityHandler.class);

    /**
     * Logs the request/response message.
     *
     * @param context
     *            The message context.
     * @return true to indicate the handler that processing should continue.
     */

    /**
     * Soap performance handler
     */

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
       
        String uri = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
        String prefix = "wsse";
        try {
             SOAPMessage message = context.getMessage();
              SOAPHeader header = message.getSOAPHeader();
            SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();

              if (header == null) {
                  header = envelope.addHeader();
              }
              QName SecurityTokenHeader = new QName(uri,"Security",prefix);
                 SOAPHeaderElement securityToken = header.addHeaderElement(SecurityTokenHeader);
                
                
             QName UsernameTokenHeader = new QName(uri,"UsernameToken",prefix);
             SOAPHeaderElement userToken = header.addHeaderElement(UsernameTokenHeader);

             QName qNameuser = new QName(uri, "Username",prefix);
             SOAPHeaderElement userHeader = header.addHeaderElement(qNameuser);
             userHeader.addTextNode("BirminghamCC");
            
             QName qNamecredentials = new QName(uri,"Password",prefix);
             SOAPHeaderElement pwdHeader = header.addHeaderElement(qNamecredentials);
             pwdHeader.addTextNode("B1rm1ngh@mCC");
            
             //securityToken.addChildElement(UsernameTokenHeader);
             userToken.addChildElement(userHeader );
             userToken.addChildElement(pwdHeader);
             securityToken.addChildElement(userToken);
             //securityToken.addAttribute(envelope.createName("S:mustUnderstand") , "1");
             message.saveChanges();
           

        } catch (SOAPException e1) {
            // TODO Auto-generated catch block
            logger.error("SOAP request error: {}", e1.getMessage());
        }
         
         

        Boolean outbound = (Boolean) context
                .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
       
        String msg = WsUtils.getMessageAsString(context.getMessage());
       
        if (Boolean.TRUE.equals(outbound))
        {
            logger.debug("SOAP request: {}", msg);
            context.put(Thread.currentThread().getId() + "OUT", msg);
        }
        else
        {
            logger.debug("SOAP response: {}", msg);
                       
            try {
                if (!(msg.contains("0<") || msg.contains("0<")))
                {
                    logger.error("no success code found");
                    throw new Exception();
                }

            }
            catch (Exception e)
            {
                writeFaultToDatabase((String)context.get(Thread.currentThread().getId() + "OUT"), msg, e);
            }
               
        }
       
       
       
       
        return true;
    }

No comments:

Post a Comment