简体   繁体   中英

Web Service Security: Client signs SOAP message (Tomcat)

We are in a hurry. We have developed a WS Client that sends data to a remote service, but SOAP message should be signed. We have generated the WS client classes from wsimport utility (JAX utilities). But it's not clear for us how to secure (sign) this SOAP messages.

I'm trying with wscompile, but getting this error:

C:\\software\\glassfish4\\glassfish\\bin>wscompile.bat -f:wsi -import efactura.wsdl -security config.xml org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 52; cvc-elt.1: No se ha encontrado la declaración del elemento 'SecurityConfiguration'. error: java.lang.RuntimeException: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 52; cvc-elt.1: No se ha encontrado la declaración del elemento 'SecurityConfiguration'.

Any clear document with the correct steps to do this?

Regards

Solved using WSS4J in a ClientHandler:

public class ClientHandler extends BasicHandler {

    private static final long serialVersionUID = 1L;

    // Opciones de seguridad

    // Localización del keystore con certificado y clave privada de usuario
    private String keystoreLocation = null;

    // Tipo de keystore
    private String keystoreType = null;

    // Clave del keystore
    private String keystorePassword = null;

    // Alias del certificado usado para firmar el tag soapBody de la petición y
    // que será alojado en el token BinarySecurityToken
    private String keystoreCertAlias = null;

    // Password del certificado usado para firmar el tag soapBody de la petición
    // y que será alojado en el token BinarySecurityToken
    private String keystoreCertPassword = null;

    /**
     * Constructor que inicializa el atributo securityOption
     *
     * @param securityOption
     *            opción de seguridad.
     * @throws Exception
     */
    public ClientHandler(Properties config) {
        if (config == null) {
            System.err.println("Fichero de configuracion de propiedades nulo");
            System.exit(-1);
        }
        try {

            keystoreLocation = config.getProperty("security.keystore.location");
            keystoreType = config.getProperty("security.keystore.type");
            keystorePassword = config.getProperty("security.keystore.password");
            keystoreCertAlias = config.getProperty("security.keystore.cert.alias");
            keystoreCertPassword = config.getProperty("security.keystore.cert.password");

        } catch (Exception e) {
            System.err.println("Error leyendo el fichero de configuración de securización");
            System.exit(-1);
        }
    }

    public void invoke(MessageContext msgContext) throws AxisFault {
        SOAPMessage secMsg = null;
        try {

            ((SOAPPart) msgContext.getRequestMessage().getSOAPPart()).setCurrentMessage(this.createBinarySecurityToken(msgContext),
                    SOAPPart.FORM_SOAPENVELOPE);

        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(-1);
        }
    }

    /**
     * Securiza, mediante el tag BinarySecurityToken y firma una petición SOAP
     * no securizada.
     *
     * @param soapEnvelopeRequest
     *            Documento xml que representa la petición SOAP sin securizar.
     * @return Un mensaje SOAP que contiene la petición SOAP de entrada
     *         securizada mediante el tag BinarySecurityToken.
     */
    private SOAPEnvelope createBinarySecurityToken(MessageContext msgContext) {
        ByteArrayOutputStream baos;
        Crypto crypto;
        Document secSOAPReqDoc,soapEnvelopeRequest;
        DOMSource source;
        Element element;
        StreamResult streamResult;
        String secSOAPReq;
        WSSecSignature wsSecSignature;
        WSSecHeader wsSecHeader;
        SOAPMessage msg;

        try {

            // Obtención del documento XML que representa la petición SOAP
            msg = msgContext.getCurrentMessage();
            soapEnvelopeRequest = ((org.apache.axis.message.SOAPEnvelope) msg.getSOAPPart().getEnvelope()).getAsDocument();

            // Inserción del tag wsse:Security y BinarySecurityToken
            wsSecHeader = new WSSecHeader(null, false);
            wsSecHeader.setMustUnderstand(true);
            wsSecSignature = new WSSecSignature();
            //crypto = CryptoFactory.getInstance("org.apache.ws.security.components.crypto.Merlin", this.initializateCryptoProperties());
            crypto = CryptoFactory.getInstance(this.initializateCryptoProperties());
            // Indicación para que inserte el tag BinarySecurityToken
            wsSecSignature.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
            // wsSecSignature.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
            wsSecSignature.setUserInfo(this.keystoreCertAlias, this.keystoreCertPassword);
            wsSecHeader.insertSecurityHeader(soapEnvelopeRequest);

            wsSecSignature.prepare(soapEnvelopeRequest, crypto, wsSecHeader);
            // Modificación y firma de la petición
            secSOAPReqDoc = wsSecSignature.build(soapEnvelopeRequest, crypto, wsSecHeader);
            element = secSOAPReqDoc.getDocumentElement();
            // Transformación del elemento DOM a String
            source = new DOMSource(element);
            baos = new ByteArrayOutputStream();
            streamResult = new StreamResult(baos);
            TransformerFactory.newInstance().newTransformer().transform(source, streamResult);
            secSOAPReq = new String(baos.toByteArray());

            // Creación de un nuevo mensaje SOAP a partir del mensaje SOAP
            // securizado formado
            Message axisMessage = getAxisMessage(secSOAPReq,msgContext);
            return axisMessage.getSOAPEnvelope();

        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(-1);
            return null;

        }
    }

    /**
     * Establece el conjunto de propiedades con el que será inicializado el
     * gestor criptográfico de WSS4J.
     *
     * @return Devuelve el conjunto de propiedades con el que será inicializado
     *         el gestor criptográfico de WSS4J.
     */
    private Properties initializateCryptoProperties() {
        Properties res = new Properties();
        res.setProperty("org.apache.ws.security.crypto.provider", "org.apache.ws.security.components.crypto.Merlin");
        res.setProperty("org.apache.ws.security.crypto.merlin.keystore.type", this.keystoreType);
        res.setProperty("org.apache.ws.security.crypto.merlin.keystore.password", this.keystorePassword);
        res.setProperty("org.apache.ws.security.crypto.merlin.keystore.alias", this.keystoreCertAlias);
        res.setProperty("org.apache.ws.security.crypto.merlin.alias.password", this.keystoreCertPassword);
        res.setProperty("org.apache.ws.security.crypto.merlin.file", this.keystoreLocation);
        return res;
    }

    /**
     * Creates and returns an Axis message from a SOAP envelope string.
     *
     * @param unsignedEnvelope
     *            a string containing a SOAP envelope
     * @return <code>Message</code> the Axis message
     */
    private Message getAxisMessage(String unsignedEnvelope, MessageContext msgContext) {
        InputStream inStream = new ByteArrayInputStream(unsignedEnvelope.getBytes());
        Message axisMessage = new Message(inStream);
        axisMessage.setMessageContext(msgContext);
        return axisMessage;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM