使用 CXF 和 WSS4J 创建封装签名

Create Enveloped Signature with CXF and WSS4J

我目前正在 Java 中借助 Apache CXF 创建一个 SOAP-Client。

我已经从给定的 WSDL 生成了服务 类 并以编程方式配置了客户端。(明确说明,我没有使用 Spring 配置)。

我调用的服务要求我发送的每个请求都需要签名。

到目前为止我所做的是创建我的客户端并添加 WSS4JOutInterceptor 以便对消息进行签名。

Client client = ClientProxy.getClient(soapService.getRawSoapInterface());

//Actually not sure if this is really needed?
QName signatureQName = new QName("http://www.w3.org/2000/09/xmldsig#", "Signature");
Map<String, Object> properties = new HashMap<String, Object>();
Map<QName, Object> processorMap = new HashMap<QName, Object>();
processorMap.put(WSSecurityEngine.SIGNATURE, signatureQName);
properties.put("wss4j.processor.map", processorMap);
properties.put(WSHandlerConstants.USER, "clientSignatureAlias");
properties.put(WSHandlerConstants.PW_CALLBACK_CLASS, MyPwCallback.class.getName());
properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
properties.put(WSHandlerConstants.SIG_PROP_FILE, "client.properties");
properties.put(WSHandlerConstants.ENC_KEY_ID, "X509KeyIdentifier");

WSS4JOutInterceptor wssOutInterceptor = new WSS4JOutInterceptor(properties);

我的 client.properties 包含:

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin
org.apache.wss4j.crypto.merlin.keystore.type=jks
org.apache.wss4j.crypto.merlin.keystore.password=secret
org.apache.wss4j.crypto.merlin.keystore.alias=cert_sig
org.apache.wss4j.crypto.merlin.keystore.file=clientCerts.jks

到目前为止一切顺利,每封邮件都在签名。

让我们进入正题: 问题是,拦截器将这些安全 Headers 放入 Soap-Request。

<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1">

起初我不知道它们,第二点是我调用的服务不知道它们,因此正在回答异常。

目前我找不到避免这种情况的方法,有什么建议吗?

据我了解,WSS4J 根本无法创建信封签名!

于是我转向了另一个方向。我使用 Apache Santuario 为我的消息创建签名。

我使用了 CXF 的 Intercepor 机制来创建我自己的拦截器,这里提供了这个用例的抽象 class:How To Modify The Raw XML message of an Outbound CXF Request? .

在那里我能够调用 Santuario STAX-API 来创建一个有效的签名,这在以下博客中描述得非常好:http://coheigea.blogspot.ie/2014/03/apache-santuario-xml-security-for-java.html

由于我对请求做了一些进一步的修改,所以我能够修改原始字符串。

感谢上帝,SOAP 是标准化协议,每个人都在做他想做的事...