我在使用 CXF WS-Security 和签名验证时遇到了问题。我WSS4JInInterceptor
在服务器端使用以验证Body
元素上的签名。
- 当我使用 e BinarySecurityToken
( DirectReference
) 作为关键标识符类型时,一切正常;
- 当我使用X509IssuerSerial
( IssuerSerial
) 作为服务器端的密钥标识符类型签名验证失败。
这是服务器端的配置:
<bean id="wss4jIn" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="Signature" />
<entry key="signaturePropFile" value="config/security/truststore.properties" />
<entry key="signatureAlgorithm" value="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<entry key="signatureKeyIdentifier" value="X509IssuerSerial"/>
<entry key="signatureParts"
value="{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body" />
</map>
</constructor-arg>
</bean>
如果我(从客户端)发送带有此 SOAPHeader 的 SOAPEnvelope:
<SOAP-ENV:Header>
<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-ENV:mustUnderstand="1">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-69c28b5e-3566-4fab-b26f-bd28e97c21e9">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="SOAP-ENV enc xsd xsi"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_e078e477-59bc-401d-83f5-a11925947d19">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="enc xsd xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>MMQ1CZWFv5ZK3KMzEpWyBVpFas73hXiedDeKyKjRUQ4=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>Amn7favWhD9RA6SHrJ6RYf6BIhdRH2N2r3WXh2+auBi3MlPstcBFA1oqBrVt3PPvTs/LZrrt6AfZWspp0YpjPEdTuDuEd1x8HrSKBgxBt+QUqfiio4WGhUJ4k/5b/loNd9D1a48ic0PloM3FsNHf+kQJeb5rPeW5f8aeRtFBUCg=</ds:SignatureValue>
<ds:KeyInfo Id="KI-b49617ba-b2d8-4bad-9c46-d772389537df">
<wsse:SecurityTokenReference wsu:Id="STR-4e662377-c736-48c5-a0c1-11a1473769ee">
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>1.2.840.113549.1.9.1=#xxx,CN=xxx,OU=xxx,O=xxx,L=xxx,ST=xx,C=xx</ds:X509IssuerName>
<ds:X509SerialNumber>xxx</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</SOAP-ENV:Header>
我会得到 SOAPFault:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode xmlns:ns1="http://ws.apache.org/wss4j">ns1:SecurityError</faultcode>
<faultstring>A security error was encountered when verifying the message</faultstring>
</soap:Fault>
</soap:Body>
使用调试日志输出,我没有得到太多信息。但是在调试时,我发现org.apache.wss4j.dom.processor.SignatureProcessor
此时失败了:
if ((certs == null || certs.length == 0 || certs[0] == null)
&& secretKey == null
&& publicKey == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
}
在 wss4j-ws-security-dom-2.1.0 中引发异常的是第 197 行。这意味着 certificate 和 publicKey 为空。这使我得出一个结论,即我从一开始就想得不够——我没有意识到没有可以验证签名的证书。另外,我的结论是,在 X509IssuerSerial 的情况下,只有在接收端(在这种情况下为服务器)端有证书的情况下,您才能验证签名。
有没有人有更好的解释?