be.fedict.hsm.client.WSSecuritySOAPHandler.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.hsm.client.WSSecuritySOAPHandler.java

Source

/*
 * HSM Proxy Project.
 * Copyright (C) 2013 FedICT.
 * Copyright (C) 2011-2012 AGIV.
 *
 * 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.fedict.hsm.client;

import java.security.PrivateKey;
import java.security.cert.X509Certificate;
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.SOAPException;
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.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;

/**
 * A JAX-WS SOAP handler that delivers the required WS-Security.
 * 
 * @author Frank Cornelis
 * 
 */
public class WSSecuritySOAPHandler implements SOAPHandler<SOAPMessageContext> {

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

    private final PrivateKey privateKey;

    private final X509Certificate certificate;

    public WSSecuritySOAPHandler(PrivateKey privateKey, X509Certificate certificate) {
        this.privateKey = privateKey;
        this.certificate = certificate;
    }

    @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) {
                throw new ProtocolException(e);
            }
        }
        return true;
    }

    private void handleOutboundMessage(SOAPMessageContext context) throws SOAPException, WSSecurityException {

        if (null == this.privateKey) {
            LOG.warn("no adding a WS-Security header");
            return;
        }

        SOAPMessage soapMessage = context.getMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();
        soapMessage.getSOAPHeader();
        WSSecHeader wsSecHeader = new WSSecHeader();
        wsSecHeader.setMustUnderstand(true);
        wsSecHeader.insertSecurityHeader(soapPart);

        WSSecTimestamp wsSecTimeStamp = new WSSecTimestamp();
        wsSecTimeStamp.prepare(soapPart);
        wsSecTimeStamp.prependToHeader(wsSecHeader);

        WSSecurityCrypto crypto = new WSSecurityCrypto(this.privateKey, this.certificate);
        WSSConfig wssConfig = new WSSConfig();
        WSSecSignature sign = new WSSecSignature(wssConfig);
        sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
        sign.prepare(soapPart, crypto, wsSecHeader);
        String bstId = sign.getBSTTokenId();
        sign.appendBSTElementToHeader(wsSecHeader);
        sign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
        sign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
        Vector<WSEncryptionPart> signParts = new Vector<WSEncryptionPart>();
        signParts.add(new WSEncryptionPart(wsSecTimeStamp.getId()));
        signParts.add(new WSEncryptionPart(WSConstants.ELEM_BODY, WSConstants.URI_SOAP12_ENV, ""));
        signParts.add(new WSEncryptionPart(bstId));
        sign.addReferencesToSign(signParts, wsSecHeader);
        List<Reference> referenceList = sign.addReferencesToSign(signParts, wsSecHeader);
        sign.computeSignature(referenceList, false, null);
    }

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

    @Override
    public void close(MessageContext context) {
    }

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