java - 将 KeyStore 与 .crt 一起使用

标签 java ssl https secure-crt

我需要将应用程序与强制使用 https 的外部 Web 服务集成。该 Web 服务的作者为我提供了 .crt 文件,我应该使用它来发出 https 请求。经过一番调查后,我发现了以下使用 KeyStore 类进行安全 https 访问的代码:

        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();

在此代码中,KeyStore 需要输入流以及密码 trustStore.load(instream, password.toCharArray());。但是,据我了解,我们在使用 .crt 文件时不需要密码。所以这种加载证书的方式不适合我。同时,根据我目前的发现,我在此处提供的代码是配置 HttpClient 以使用 SSL 证书的唯一方法。是否有任何解决方法来配置 HttpClient 以使用 .crt 证书?

谢谢,

安德烈

最佳答案

我假设 Web 服务正在为您提供自签名证书(即不是由知名 CA 签名的)。如果它已由 Java 的 cacerts 文件中的知名 CA 签名,则您无需执行任何操作。

否则,您有几个选择:

  1. 将证书导入全局 cacerts keystore
  2. 使用特定于应用程序的 keystore 启动您的应用程序

无论哪种情况,您首先需要将 crt 文件转换为 Java 使用的 jks keystore 。您可以通过以下方式执行此操作:

$ keytool -import -keystore mykeystore.jks -storepass horsestaple

请注意,keytool 需要提供密码(上面的 horsestaple)才能创建 jks 存储。你可以把任何东西放在那里;正如你所说,公共(public)网站证书不需要密码保护,毕竟它们是公开的。

如果您正在执行选项 1,请备份您的 cacerts 并提供 cacerts 文件而不是 mykeystore.jks。有关 cacerts 的位置,请参阅下面的链接。对于此选项,您已准备就绪,您的应用程序应通过 HTTPS 连接到 Web 服务,无需任何其他配置,因为 Java 默认加载 cacerts。

如果您正在执行选项 2,这可能至少在测试阶段是首选,您需要使用此参数运行您的应用程序:

-Djavax.net.ssl.trustStore=mykeystore.jks

这是一个 JVM 参数,因此请适本地提供它。这取决于您运行应用程序的方式。

请注意,在这种情况下您将只有导入的证书,因此您的其他 HTTPS 连接将不起作用。您可以通过首先将标准 cacerts 复制到一个临时位置,将 key 导入其中并在上面的命令中使用它来避免这种情况。这将为您提供所有标准证书,以及您需要的证书。

选项 2 的一个小缺点是,如果添加或撤销新证书,您的应用程序特定 keystore 将不会更新。如果这是一个问题,您可以即时合并 keystore ,例如:

无论哪种情况,您现在都应该能够进行标准的 URL 提取,例如此处给出的示例:

即:

final URL url = new URL("https://example.com");
try(final InputStream in = url.openStream()){
  //…
}

更多信息在这里:

  • key 工具和一般证书信息

https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html

  • 证书地点

http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html

  • 导入自签名证书的更多选项

How to properly import a selfsigned certificate into Java keystore that is available to all Java applications by default?

关于java - 将 KeyStore 与 .crt 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38851378/

相关文章:

java - 如何将 Hessian 与 Guice 集成?

Java REST Web 服务 404 错误

java - 如何创建一个也处理原始 int 的 ParamConverter<Integer> ?

android - 使用 okHttp 固定证书

http - 确保 JSF 网页未根据 YSlow 进行缓存

java - UnicodeFont 渲染似乎阻止了其他所有内容的渲染?

ssl - 如何将SSL证书导入系统?

所有域的 SSL 证书

android - 如何在 Retrofit 中使用 ssl 证书发出 https 请求

https - Pyramid pserve 服务器作为 https