be.e_contract.dssp.client.WSSecuritySOAPHandler.java Source code

Java tutorial

Introduction

Here is the source code for be.e_contract.dssp.client.WSSecuritySOAPHandler.java

Source

/*
 * Digital Signature Service Protocol Project.
 * Copyright (C) 2013-2014 e-Contract.be BVBA.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.e_contract.dssp.client;

import java.util.List;
import java.util.Set;
import java.util.Vector;

import javax.xml.crypto.dsig.Reference;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.ProtocolException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecTimestamp;
import org.apache.ws.security.message.WSSecUsernameToken;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Element;

/**
 * WS-Security JAX-WS SOAP handler. Creates a WS-Security signature using the
 * WS-SecureConversation security token or a WS-Security username/password
 * header.
 * 
 * @author Frank Cornelis
 * 
 */
public class WSSecuritySOAPHandler implements SOAPHandler<SOAPMessageContext> {

    private static final Log LOG = LogFactory.getLog(WSSecuritySOAPHandler.class);

    private DigitalSignatureServiceSession session;

    private String username;

    private String password;

    /**
     * Sets the session object to be used for constructing the WS-Security SOAP
     * header.
     * 
     * @param session
     */
    public void setSession(DigitalSignatureServiceSession session) {
        this.session = session;
        this.username = null;
        this.password = null;
    }

    /**
     * Sets the WS-Security username/password credentials.
     * 
     * @param username
     * @param password
     */
    public void setCredentials(String username, String password) {
        this.username = username;
        this.password = password;
        this.session = null;
    }

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        if (true == outboundProperty.booleanValue()) {
            try {
                handleOutboundMessage(context);
            } catch (Exception e) {
                LOG.error("outbound exception: " + e.getMessage(), e);
                throw new ProtocolException(e);
            }
        }
        return true;
    }

    private void handleOutboundMessage(SOAPMessageContext context) throws WSSecurityException, SOAPException {
        if (null == this.session && null == this.username) {
            return;
        }
        SOAPMessage soapMessage = context.getMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();

        SOAPHeader soapHeader;
        try {
            soapHeader = soapMessage.getSOAPHeader();
        } catch (SOAPException e) {
            // WebSphere 8.5.5.1 work-around.
            soapHeader = null;
        }
        if (null == soapHeader) {
            /*
             * Work-around for Axis2.
             */
            SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
            soapHeader = soapEnvelope.addHeader();
        }

        WSSecHeader wsSecHeader = new WSSecHeader();
        Element securityElement = wsSecHeader.insertSecurityHeader(soapPart);

        if (null != this.session) {
            securityElement.appendChild(
                    securityElement.getOwnerDocument().importNode(this.session.getSecurityTokenElement(), true));
        }

        WSSecTimestamp wsSecTimeStamp = new WSSecTimestamp();
        wsSecTimeStamp.setTimeToLive(60);
        wsSecTimeStamp.build(soapPart, wsSecHeader);

        if (null != this.username) {
            WSSecUsernameToken usernameToken = new WSSecUsernameToken();
            usernameToken.setUserInfo(this.username, this.password);
            usernameToken.setPasswordType(WSConstants.PASSWORD_TEXT);
            usernameToken.prepare(soapPart);
            usernameToken.prependToHeader(wsSecHeader);
        }

        if (null != this.session) {
            // work-around for WebSphere
            WSSConfig wssConfig = new WSSConfig();
            wssConfig.setWsiBSPCompliant(false);

            WSSecSignature wsSecSignature = new WSSecSignature(wssConfig);
            wsSecSignature.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
            wsSecSignature.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
            wsSecSignature.setCustomTokenId(this.session.getSecurityTokenElement().getAttributeNS(
                    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id"));
            wsSecSignature.setSecretKey(this.session.getKey());
            wsSecSignature.prepare(soapPart, null, wsSecHeader);
            Vector<WSEncryptionPart> signParts = new Vector<WSEncryptionPart>();
            SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(soapPart.getDocumentElement());
            signParts.add(new WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),
                    soapConstants.getEnvelopeURI(), "Content"));
            signParts.add(new WSEncryptionPart(wsSecTimeStamp.getId()));
            List<Reference> referenceList = wsSecSignature.addReferencesToSign(signParts, wsSecHeader);
            wsSecSignature.computeSignature(referenceList, false, null);
        }

        /*
         * Really needs to be at the end for Axis2 to work. Axiom bug?
         */
        appendSecurityHeader(soapHeader, securityElement);
    }

    private void appendSecurityHeader(SOAPHeader soapHeader, Element securityElement) {
        soapHeader.removeChild(securityElement);
        soapHeader.appendChild(securityElement);
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        return true;
    }

    @Override
    public void close(MessageContext context) {
    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }
}