使用KeyStore与.crt
我需要集成一个应用程序与强制使用https的外部Web服务。此Web服务的作者为我提供了.crt文件,我应该使用它来提供https请求。经过一番调查,我发现下面的代码,它使用KeyStore类为安全HTTPS访问:使用KeyStore与.crt
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(file));
try {
trustStore.load(instream, password.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext =
SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
SSLConnectionSocketFactory sslsf =
new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null,
BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
HttpClients.custom().setSSLSocketFactory(sslsf).build();
在这段代码密钥库,需要输入流与密码trustStore.load(instream, password.toCharArray())
一起。不过,据我所知,使用.crt文件时我们不需要密码。所以这种加载证书的方式并不适合我。同时,从我迄今为止发现的情况来看,我在这里提供的代码是配置HttpClient使用SSL证书的唯一方法。是否有任何解决方法来配置HttpClient使用.crt证书?
感谢,
安德烈
我假定Web服务为您提供一个自签名证书(即不是由知名CA签名)。如果它已经由Java的cacerts文件中的知名CA签名,则不需要执行任何操作。
否则,你有两个选择:
- 证书导入全球的cacerts密钥存储
- 启动与专用密钥库
在这两种情况下,你首先需要您的应用程序将crt文件转换为Java使用的jks keystore。你可以这样做:
$ keytool -import -keystore mykeystore.jks -storepass horsestaple
注意,密钥工具需要创建JKS存储要提供的密码(以上horsestaple
)。你可以放任何东西;如你所说,公共网站证书不需要密码保护,毕竟他们是公开的。
如果您正在做选项1,请备份您的cacerts并提供cacerts文件而不是mykeystore.jks。请参阅以下链接,了解cacerts的位置。对于这个选项,你已经全部设置了,你的应用程序应该通过HTTPS连接到Web服务,而不需要任何额外的配置,因为默认情况下Java会加载cacerts。
如果你正在做的选项2,这可能是至少首选测试阶段,你需要使用这个参数运行应用程序:
-Djavax.net.ssl.trustStore=mykeystore.jks
这是一个JVM的参数,所以适当地提供它。这取决于你如何运行你的应用程序。
请注意,在这种情况下您将只有导入的证书,因此您的其他HTTPS连接将不起作用。您可以通过首先将标准cacerts复制到临时位置,将密钥导入并在上面的命令中使用它来避免这种情况。这将给你所有的标准证书,加上你需要的。
选项2的一个小缺点是,如果新证书被添加或撤销,您的特定于应用程序的密钥库不会被更新。如果这是一个问题,你可以在飞行合并密钥库,例如:
在这两种情况下,你现在应该能够只是做一个标准的网址提取,如例如在这里给出:
即:
final URL url = new URL("https://example.com");
try(final InputStream in = url.openStream()){
//…
}
点击此处了解详情:
- 使用Keytool和证书的一般信息
https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
- cacerts的位置
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html
- 更多选择导入自签名证书
希望这有助于。
除非他们与应该用于验证连接到他们他们 .crt文件,这表明他们正在使用自签名证书提供你,他们没有任何有用您提供。如果您需要证书作为客户端,您需要的第一件事是公钥/私钥对,您可以从中生成一个您签署的CSR。没有其他人可以安全地提供除签名证书之外的任何内容。
如果他们已经提供了自己的(自签名?)证书,则需要将其加载到一个信任,而不是一个密钥库,通过keytool
与-trustcacerts
选项,然后告诉Java使用信任,可以通过javax.net.ssl.trustStore
系统属性或通过构建您自己的TrustManager
并将其提供给自定义SSLContext
,如JSSE参考指南中所述。
第三种选择是直接将信任库用于客户端API,这是OP看起来像他们正在做的事情。这比你最初提出的两个选项中的任何一个都好,因为它不会干扰任何其他信任商店的使用。 –
@ChristopherSchultz同意,如果OP想要使用原来的解决方案,当然可以。我想这取决于用例,如果分布在多个应用程序中,更新全局cacerts可能会更容易。 –