java 签署 JAX-WS SOAP 请求

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7598338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:38:11  来源:igfitidea点击:

Sign JAX-WS SOAP request

javasoapjax-wsx509

提问by AndrewBourgeois

I would like to write a JAX-WS web service that signs my SOAP messages using the http://www.w3.org/TR/xmldsig-core/recommendation.

我想编写一个 JAX-WS Web 服务,使用http://www.w3.org/TR/xmldsig-core/推荐对我的 SOAP 消息进行签名。

With what I found on the internet I wrote a JAX-WS handler (SOAPHandler<SOAPMessageContext>) that manages to change a copy of the SOAP request:

使用我在 Internet 上找到的内容,我编写了一个 JAX-WS 处理程序 ( SOAPHandler<SOAPMessageContext>),它可以更改 SOAP 请求的副本:

@Override
public boolean handleMessage(SOAPMessageContext smc) {
    Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    SOAPMessage message = smc.getMessage();

    if (outboundProperty) {
        try {
            SOAPPart soapPart = message.getSOAPPart();
            SOAPEnvelope soapEnvelope = soapPart.getEnvelope();

            Source source = soapPart.getContent();

            Node root = null;
            Document doc22 = null;
            if (source instanceof DOMSource) {
                root = ((DOMSource) source).getNode();
            } else if (source instanceof SAXSource) {
                InputSource inSource = ((SAXSource) source).getInputSource();
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                dbf.setNamespaceAware(true);
                DocumentBuilder db = null;

                db = dbf.newDocumentBuilder();

                doc22 = db.parse(inSource);
                root = (Node) doc22.getDocumentElement();
            }

            XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");

            Reference ref = fac.newReference("", fac.newDigestMethod(DigestMethod.SHA1, null),
                    Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
                    null, null);

            SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                    (C14NMethodParameterSpec) null),
                    fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                    Collections.singletonList(ref));

            // Load the KeyStore and get the signing key and certificate.
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("client_keystore.jks"), "changeit".toCharArray());
            KeyStore.PrivateKeyEntry keyEntry =
                    (KeyStore.PrivateKeyEntry) ks.getEntry("client", new KeyStore.PasswordProtection("changeit".toCharArray()));
            X509Certificate cert = (X509Certificate) keyEntry.getCertificate();
            // Create the KeyInfo containing the X509Data.
            KeyInfoFactory kif2 = fac.getKeyInfoFactory();
            List x509Content = new ArrayList();
            x509Content.add(cert.getSubjectX500Principal().getName());
            x509Content.add(cert);
            X509Data xd = kif2.newX509Data(x509Content);
            KeyInfo ki = kif2.newKeyInfo(Collections.singletonList(xd));

            Element header = getFirstChildElement(root/*.getDocumentElement()*/);
            DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), header /*doc.getDocumentElement()*/);

            XMLSignature signature = fac.newXMLSignature(si, ki);

            signature.sign(dsc);

            //TODO: change this to update the SOAP message, not write it to disks
            OutputStream os = new FileOutputStream("out.xml");
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(root), new StreamResult(os));

        } catch (Exception ex) {
            System.out.println(ex);
        }
    }

    return true;
}

But I can't figure out how to update the SOAP request?

但我不知道如何更新 SOAP 请求?

回答by zacheusz

The simplest way is to use functionality integrated in application server. For example :Securing JAX-WS Web services using message-level security with WebSphere App Server

最简单的方法是使用集成在应用服务器中的功能。例如:使用 WebSphere App Server 的消息级安全保护 JAX-WS Web 服务

How to configure signing on WAS you can find here.

您可以在此处找到如何在 WAS 上配置签名。

And here is WebLogic documentation about Configuring Message-Level Security.

这是关于配置消息级安全性的 WebLogic 文档

回答by linkamp

I develop a SOAPHandler for Xml Digital Signature of Soap Request.

我为 Soap 请求的 Xml 数字签名开发了一个 SOAPHandler。

public class SOAPSecurityHandler implements
        LogicalHandler<LogicalMessageContext> {

    static final String KEYSTORE_FILE = "keystore_name.jks";
    static final String KEYSTORE_INSTANCE = "JKS";
    static final String KEYSTORE_PWD = "123456";
    static final String KEYSTORE_ALIAS = "keystore";

    public Set<QName> getHeaders() {
        return Collections.emptySet();
    }

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

        try {

            if (outboundProperty) {

                Source source = smc.getMessage().getPayload();

                Node root = null;

                root = ((DOMSource) source).getNode();

                XMLSignatureFactory fac = XMLSignatureFactory
                        .getInstance("DOM");

                Reference ref = fac.newReference("", fac.newDigestMethod(
                        DigestMethod.SHA1, null), Collections.singletonList(fac
                        .newTransform(Transform.ENVELOPED,
                                (TransformParameterSpec) null)), null, null);

                SignedInfo si = fac.newSignedInfo(fac
                        .newCanonicalizationMethod(
                                CanonicalizationMethod.INCLUSIVE,
                                (C14NMethodParameterSpec) null), fac
                        .newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                        Collections.singletonList(ref));

                // Load the KeyStore and get the signing key and certificate.
                KeyStore ks = KeyStore.getInstance(KEYSTORE_INSTANCE);
                ks.load(new FileInputStream(KEYSTORE_FILE),
                        KEYSTORE_PWD.toCharArray());
                KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks
                        .getEntry(
                                KEYSTORE_ALIAS,
                                new KeyStore.PasswordProtection(KEYSTORE_PWD
                                        .toCharArray()));
                X509Certificate cert = (X509Certificate) keyEntry
                        .getCertificate();
                // Create the KeyInfo containing the X509Data.
                KeyInfoFactory kif2 = fac.getKeyInfoFactory();
                List x509Content = new ArrayList();
                x509Content.add(cert.getSubjectX500Principal().getName());
                x509Content.add(cert);
                X509Data xd = kif2.newX509Data(x509Content);
                KeyInfo ki = kif2.newKeyInfo(Collections.singletonList(xd));

                Element header = DOMUtils.getFirstChildElement(root);
                DOMSignContext dsc = new DOMSignContext(
                        keyEntry.getPrivateKey(), header);

                XMLSignature signature = fac.newXMLSignature(si, ki);

                signature.sign(dsc);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;

    }

    public boolean handleFault(SOAPMessageContext smc) {
        // addDigitalSignature(smc);
        return true;
    }

    // nothing to clean up
    public void close(MessageContext messageContext) {
    }

    @Override
    public boolean handleFault(LogicalMessageContext arg0) {
        // TODO Auto-generated method stub
        return false;
    }

}

I think the problem in code of @AndrewBourgeois is the way of get Source.

我认为@AndrewBourgeois 代码中的问题是获取Source 的方式。

Regards,

问候,

回答by vidsc

You can try soapPart.saveChanges();

你可以试试soapPart.saveChanges();

回答by Roy

After the code line:

在代码行之后:

signature.sign(dsc);

insert this statement:

插入此语句:

soapMsg.saveChanges();

It will save your changes.

它将保存您的更改。