我有一个在Tomcat中运行的java应用程序。它正在尝试访问经过TLS客户端证书验证的SOAP服务。正在使用的所有证书都是自签名的。我通过Tomcat中的Java Options指定了trustStore和keyStore,我还尝试在创建服务之前在代码中为所有需要的属性执行此操作。 keyStore和trustStore都是带有RSA证书的JKS。我已经验证了服务器的trustStore中存在的证书,并且客户端密钥库中存在自客户端证书,并且哈希是相同的。
客户方:
c:\Program Files\Java\jre7\bin>keytool -list -keystore c:\tomcat\certs\tomcat.keystore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
tomcat, Jan 20, 2014, PrivateKeyEntry,
Certificate fingerprint (SHA1): 78:F3:30:A0:40:B0:CC:8D:86:1F:99:FF:7C:3B:85:7C:6D:C7:F2:D2
服务器端:
C:\Program Files (x86)\Java\jre7\bin>keytool -list -keystore c:\tomcat\certs\tomcat.truststore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
clientcert, Jan 23, 2014, trustedCertEntry,
Certificate fingerprint (SHA1): 78:F3:30:A0:40:B0:CC:8D:86:1F:99:FF:7C:3B:85:7C:6D:C7:F2:D2
当我启动Tomcat时,我看到像这样加载密钥库:
keyStore is : c:\tomcat\certs\tomcat.keystore
keyStore type is : JKS
keyStore provider is :
init keystore
init keymanager of type SunX509
***
found key for : tomcat
chain [0] = [
[
Version: V3
Subject: CN=Name, OU=Engineering, O=MyOrg, ST=NJ, C=US
...
在服务器问候结束时,我看到了我期望并从上面的密钥库加载的证书DN:
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Cert Authorities:
<CN=Name, OU=Engineering, O=MyOrg, ST=NJ, C=US>
[read] MD5 and SHA1 hashes: len = 115
...
然后在ServerHelloDone之后立即看到一个没有“匹配别名:mycert”的空证书链,就像我希望看到的那样。
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
*** Certificate chain
***
服务器端我得到了这个:
http-nio-8443-exec-2, READ: TLSv1 Handshake, length = 269
*** Certificate chain
***
http-nio-8443-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
http-nio-8443-exec-2, SEND TLSv1 ALERT: fatal, description = bad_certificate
http-nio-8443-exec-2, WRITE: TLSv1 Alert, length = 2
http-nio-8443-exec-2, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
http-nio-8443-exec-2, called closeOutbound()
http-nio-8443-exec-2, closeOutboundInternal()
当我拿到客户端的证书并将其加载到我的浏览器并导航到该站点时,系统会提示我选择证书并能够查看wsdl等。所以我相信证书很好。
Java客户端使用它在Java选项中指定的trustStore就好了验证服务器,这让我相信trustStore已加载并使用得很好。最后,这是我认为负责创建服务的客户端代码:
System.setProperty("javax.net.ssl.keyStore","C:\\tomcat\\certs\\tomcat.keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("javax.net.ssl.keyStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore","C:\\tomcat\\certs\tomcat.truststore");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
URL url = DocumentRepositoryProxy.class.getClassLoader().getResource("XDS.b_DocumentRepositoryWSDLSynchMTOM.wsdl");
QName qname = new QName("urn:ihe:iti:xds-b:2007", "DocumentRepository_Service");
DocumentRepositoryService service = new DocumentRepositoryService(url, qname);
if (handlerResolver != null)
service.setHandlerResolver(handlerResolver);
proxy = service.getDocumentRepositoryPortSoap12(new MTOMFeature(true, 1));
BindingProvider bp = (BindingProvider) proxy;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
我花了一个星期的大部分时间来走下这个兔子洞,如果有人能帮忙的话,我会省下一些毛发。
答案 0 :(得分:1)
这是答案。在我的WebApp的WEB-INF / cxf-servlet.xml文件中,我需要添加这个XML块和相关的命名空间。代码中的Java选项被完全忽略,因此我删除了它们。一旦我添加了这个并重新启动了Tomcat,一切都在第一次尝试。
命名空间:
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
元素:
<http:conduit name="*.http-conduit">
<http:tlsClientParameters>
<sec:keyManagers keyPassword="XXX">
<sec:keyStore type="JKS"
password="password"
file="C:/tomcat/certs/tomcat.keystore"/>
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS"
password="password"
file="C:\tomcat\certs\tomcat.truststore"/>
</sec:trustManagers>
</http:tlsClientParameters>
</http:conduit>