我在使用CXF WS-Security和签名验证时遇到了问题。我在服务器端使用WSS4JInInterceptor
以验证Body
元素上的签名
- 当我使用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);
}
第197行在wss4j-ws-security-dom-2.1.0中抛出异常。这意味着certificate和publicKey为null。这让我得出结论,我从一开始就没有足够的思考 - 我没有意识到没有证书可以验证签名。另外,我的结论是,在X509IssuerSerial的情况下,只有在您收到证书(在本例中为服务器端)时才能验证签名。
有没有人有更好的解释?