java - Web 服务安全 : Client signs SOAP message (Tomcat)

标签 java web-services tomcat soap ws-security

我们很着急。我们开发了一个将数据发送到远程服务的 WS 客户端,但应该对 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;行号:1;列数:52; cvc-elt.1: No se ha encontrado la declaración del elemento 'SecurityConfiguration'。 错误:java.lang.RuntimeException:org.xml.sax.SAXParseException;行号:1;列数:52; cvc-elt.1: No se ha encontrado la declaración del elemento 'SecurityConfiguration'。

是否有明确的文档以及执行此操作的正确步骤?

问候

最佳答案

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

关于java - Web 服务安全 : Client signs SOAP message (Tomcat),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37574010/

相关文章:

web-services - RESTful 触发服务器端事件的方式

.net - 为 web 服务、soap 和 rest 创建测试用例

java - 可以在 Eclipse 外的 tomcat 中部署 war,但不能在 Eclipse 中的 Tomcat 中部署 war

java - servlet 上下文的多个动态数据源

java - 使用 AsyncTask 进行 android 网络连接

java - 如何将 3x3 二维数组顺时针旋转 n 次

java - 生成了错误的 SOAP 请求

tomcat - Azure Web应用程序Tomcat 8配置

java - 重新启动后无法访问另一个类中的 SharedPreferences 值

java - 无法执行安装管理器文件