我正在用Java编写一个应用程序,它通过HTTPS连接到两个Web服务器.一个通过默认的信任链获得证书,另一个使用自签名证书.当然,连接到第一台服务器是开箱即用的,而在我使用该服务器的证书创建一个trustStore之前,使用自签名证书连接到服务器不起作用.但是,与默认可信服务器的连接不再起作用,因为显然我创建自己的默认trustStore会被忽略.
我找到的一个解决方案是将证书从默认的trustStore添加到我自己的.但是,我不喜欢这个解决方案,因为它需要我继续管理那个trustStore.(我不能假设这些证书在可预见的未来仍然是静态的,对吧?)
除此之外,我发现了两个有着类似问题的5岁线程:
他们都深入到Java SSL基础架构.我希望到现在有一个更方便的解决方案,我可以在我的代码的安全审查中轻松解释.
我们的系统中有一些代码用于自动生成自签名证书到密钥存储区,然后由Jetty使用.如果给定主机的密钥已经存在,则没有任何反应,但如果它不存在,我们会生成一个新密钥,如下所示:
public void generateKey(String commonName) {
X500Name x500Name = new X500Name("CN=" + commonName);
CertAndKeyGen keyPair = new CertAndKeyGen("DSA", "SHA1withDSA");
keyPair.generate(1024);
PrivateKey privateKey = keyPair.getPrivateKey();
X509Certificate certificate = keyPair.getSelfCertificate(x500Name, 20*365*24*60*60);
Certificate[] chain = { certificate };
keyStore.setEntry(commonName, privateKey, "secret".toCharArray(), chain);
}
Run Code Online (Sandbox Code Playgroud)
只要密钥库中只有一个密钥和证书,这一切都可以正常工作.一旦你有多个密钥,当你尝试连接时会发生奇怪的事情:
java.io.IOException: HTTPS hostname wrong: should be <127.0.0.1>
Run Code Online (Sandbox Code Playgroud)
这是一个非常神秘的错误,但我终于设法通过编写连接到服务器的单元测试来跟踪它,并断言证书上的CN与主机名匹配.我发现非常有趣 - Jetty似乎随意选择向客户提供哪种证书,但是以一致的方式.
例如:
我编写了一些代码,这些代码循环遍历商店中的证书以将其打印出来,并发现它并非始终如一地选择第一个证书或类似的任何小问题.
那么它究竟使用什么标准呢?最初我认为localhost很特别,但第三个例子完全让我感到困惑.
我认为这是由KeyManagerFactory以某种方式决定的,在我的情况下是SunX509.
我有一些应用程序需要在同一个应用程序服务器中运行.每个应用程序都需要使用特定于该应用程序的证书通过同一Web服务进行身份验证.显然,我可以将所有证书放在同一个密钥库中,但是如何指定我必须使用哪个?对于我正在使用Spring WebServiceTemplate的调用,我想找到一些可以在spring xml配置文件中轻松配置的东西.
我试图遵循这个: 如何为Java服务器提供多个SSL证书
整个概念很清楚但我无法理解如何将它与Spring WebServiceTemplate链接以及如何在调用内部指定我必须使用的证书.
java ×3
ssl ×3
certificate ×1
https ×1
jetty ×1
keystore ×1
spring ×1
spring-ws ×1
truststore ×1