Web服务安全性:客户端签署SOAP消息(Tomcat)

时间:2016-06-01 16:21:07

标签: java web-services tomcat soap ws-security

我们很着急。我们开发了一个将数据发送到远程服务的WS Client,但是应该签署SOAP消息。我们已经从wsimport实用程序(JAX实用程序)生成了WS客户端类。但是我们不清楚如何保护(签署)这些SOAP消息。

我正在尝试使用wscompile,但收到此错误:

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:没有任何关于“安全配置”的声明。 error:java.lang.RuntimeException:org.xml.sax.SAXParseException; lineNumber:1; columnNumber:52; cvc-elt.1:没有任何关于“安全配置”的声明。

任何明确的文件都有正确的步骤来执行此操作吗?

此致

1 个答案:

答案 0 :(得分:0)

在ClientHandler中使用WSS4J解决:

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;
    }
}