仅使用CA证书而不是密钥库的情况下使用SSLContext

24

我需要为 Jersey-Client 应用程序设置一个 javax.net.ssl.SSLContext。我只想让上下文接受自定义根 CA 证书。真的没有其他方法可以避免生成一个密钥库文件并导入 CA 证书吗?

1个回答

49

真的没有办法绕过生成密钥库文件和导入CA证书吗?

有一些方法可以不使用密钥库文件,但是由于您必须以某种方式加载要信任的CA证书,因此您必须以某种方式加载文件或资源。

(您当然也可以实现自己的 TrustManager,使所有调用使用Certification Path API,而不使用 KeyStore API,但这只会增加代码的复杂性,而不是减少它。您还需要了解 Java PKI程序员指南 才能正确执行此操作。)

如果您真的不想要密钥库文件,可以在内存中使用 KeyStore API 直接加载证书。

类似以下内容应该可以工作(未经测试):

InputStream is = new FileInputStream("cacert.crt");
// You could get a resource as a stream instead.

CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate)cf.generateCertificate(is);

TrustManagerFactory tmf = TrustManagerFactory
    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null); // You don't need the KeyStore instance to come from a file.
ks.setCertificateEntry("caCert", caCert);

tmf.init(ks);

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

(记得关闭所有内容并处理异常。)

无论是通过这种方式加载证书还是从密钥库文件中将证书加载到类似的KeyStore实例中,哪种更方便由您决定。


8
对于任何看到这篇答案的人,请确保使用导入javax.net.ssl.TrustManagerFactory而不是com.sun.net.ssl.TrustManagerFactory;后者现已被弃用。谢谢。 - Matt Clark
5
一般情况下,你不应该直接导入任何com.sun.*或者sun.*的包。 - Bruno
1
在我的情况下,证书是由用户(通过设置)添加的,并以Base64字符串形式到达:java.io.InputStream is = new java.io.ByteArrayInputStream( java.util.Base64.getDecoder().decode(cert) ); 运行得很好。谢谢! - mvreijn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接