我将此问题追查到一个证书提供者,该提供者不属于默认的 JVM 受信任主机,截至JDK 8u74
. 提供商是www.identrust.com,但这不是我试图连接的域。该域已从该提供商处获得其证书。请参阅JDK/JRE 中的默认列表是否会覆盖跨根目录的信任?- 阅读几个条目。另请参阅哪些浏览器和操作系统支持 Let's Encrypt。
因此,为了连接到我感兴趣的域,该域具有从identrust.com
我颁发的证书,我执行了以下步骤。基本上,我必须获得 identrust.com ( DST Root CA X3
) 证书才能被 JVM 信任。我可以像这样使用 Apache HttpComponents 4.5 做到这一点:
1:在证书链下载说明中从 indettrust 获取证书。单击DST 根 CA X3链接。
2:将字符串保存到名为“DST Root CA X3.pem”的文件中。请务必在文件的开头和结尾添加“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----”行。
3:使用以下命令创建一个 java 密钥库文件 cacerts.jks:
keytool -import -v -trustcacerts -alias IdenTrust -keypass yourpassword -file dst_root_ca_x3.pem -keystore cacerts.jks -storepass yourpassword
4:将生成的 cacerts.jks 密钥库复制到 java/(maven) 应用程序的资源目录中。
5:使用以下代码加载此文件并将其附加到 Apache 4.5 HttpClient。这将解决所有具有从indetrust.com
util oracle 颁发的证书的域的问题,该证书将证书包含在 JRE 默认密钥库中。
SSLContext sslcontext = SSLContexts.custom()
.loadTrustMaterial(new File(CalRestClient.class.getResource("/cacerts.jks").getFile()), "yourpasword".toCharArray(),
new TrustSelfSignedStrategy())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] { "TLSv1" },
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
当项目构建时,cacerts.jks 将被复制到类路径中并从那里加载。此时我没有针对其他 ssl 站点进行测试,但是如果上面的代码“链”在这个证书中,那么它们也可以工作,但是我不知道。
参考:自定义 SSL 上下文和如何接受带有 Java HttpsURLConnection 的自签名证书?