首页 > 解决方案 > 我是否应该始终在我的 WebClient 中明确加载 keyStore 以获取授权服务?

问题描述

我有一个 java 密钥库,可以通过它连接到受保护的 https 第三方服务。当我初始化我的网络客户端时,我在我的代码中明确地使用了这个密钥库:

// Solution #1
String password = "changeit";
KeyStore keyStore = KeyStore.getInstance(new File("src/main/resources/keystore.jks"), password.toCharArray());

SSLContext sslContext = new SSLContextBuilder()
    .loadKeyMaterial(keyStore, password.toCharArray())
    .build();

SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, (hostname, session) -> true);

HttpClient httpClient = HttpClients.custom()
    .setSSLSocketFactory(socketFactory)
    .build();

使用这种方法,一切正常。

但我也知道有可能指定系统变量javax.net.ssl.keyStorejavax.net.ssl.keyStorePassword. 所以我期待上面代码的替代解决方案也可以工作:

// Solution #2
System.setProperty( "javax.net.ssl.keyStore", "src/main/resources/keystore.jks");
System.setProperty( "javax.net.ssl.keyStorePassword", "changeit"); 
HttpClient httpClient = HttpClients.createDefault();

我创建了一个默认的 Web 客户端,而不用我的密钥库显式地构造 SSLContext。我预计默认的 Web 客户端会以某种方式自动从javax.net.ssl.keyStore. 但它似乎没有采取,这个解决方案对我不起作用。

所以我想知道使用系统属性的目的是什么javax.net.ssl.keyStore?它如何有用?这里的最佳做法是什么?

标签: javasslkeystore

解决方案


根据@Bruno 在How to access jvm default KeyStore?中的回答 java中没有默认值KeyStore。这意味着如果你运行应用程序

-Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.ssl.keyStore=/opt/app/certificates/keyStore.jks

这还需要在您的代码中解析它们,例如

  private static final String filePath = System.getProperty("javax.net.ssl.keyStore");
  private static final String password = System.getProperty("javax.net.ssl.keyStorePassword");

然后在您的HttpClient(如 in Solution #1)中显式使用。换句话说,keyStore如果您不手动解析它们并且不将它们用于您的HttpClient. 这就是我发布问题时试图理解的内容。

TrustStore这是与类似系统属性的重要区别

-Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.trustStore=/opt/app/certificates/cacert

指定这些属性不需要任何额外的代码。因为有一个默认值TustStore,它将由JVM属性自动创建。然后httpClient将只使用该默认值TrustStore,而无需开发人员的任何努力。


推荐阅读