java—我是否应该始终在授权服务的webclient中显式加载密钥库?

txu3uszq  于 2021-06-30  发布在  Java
关注(0)|答案(3)|浏览(433)

我有一个java密钥库,可以用它连接到受保护的https第三方服务。在初始化web客户端时,我会在代码中明确使用此密钥库:

// 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.keyStore 以及 javax.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 ? 它如何有用?这里的最佳做法是什么?

jtoj6r0c

jtoj6r0c1#

您可以执行与第一个解决方案类似的操作,但必须将密码作为 String ,密码应在 properties 在运行时加载的文件,或在启动jvm时将其指定为环境变量。
我想说的重点是密码不应该在代码中。
对于第二个解决方案,您可能需要检查 trustStore 环境变量。
https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslserver.html

8wtpewkr

8wtpewkr2#

与@bruno在如何访问jvm默认密钥库中的答案相对应?没有默认值 KeyStore 在 java 。这意味着如果你用

-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 (如在 Solution #1 ). 换句话说,只需指定 keyStore 如果您不手动解析它们,也不将它们用于 HttpClient . 这就是我在发布问题时试图理解的。
这是与系统属性的一个重要区别 TrustStore 喜欢

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

指定这些属性不需要任何额外的代码。因为有一个默认值 TustStore 将由自动创建 JVM 从属性。那么 httpClient 将只使用默认值 TrustStore 没有开发商的任何努力。

mnemlml8

mnemlml83#

设置信任库 javax.net.ssl.trustStore 为公众证书提供外部服务。 javax.net.ssl.keyStore 用于在https上运行时存储您的私有证书。

// Your private cert location
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
System.setProperty("javax.net.ssl.keyStore", env.getProperty(SSL_KEYSTORE));
System.setProperty("javax.net.ssl.keyStorePassword", env.getProperty(SSL_KEYSTORE_PASS));
// Public cert location
System.setProperty("javax.net.ssl.trustStoreType", "pkcs12");
System.setProperty("javax.net.ssl.trustStore", env.getProperty(SSL_TRUSTSTORE));
System.setProperty("javax.net.ssl.trustStorePassword", env.getProperty(SSL_TRUSTSTORE_PASS));

另外,我建议从一个单独的属性文件加载属性(特别是密码),如lé哦,施耐德。
更新您关于 javax.net.ssl 属性,这些属性是定义信任库和密钥库属性的替代方法。它是有用的b/c不是所有的库都允许sslcontext作为可能需要的输入(例如不支持ssl的遗留库)。此外,还可以直接从命令行定义这些属性,从而提高可用性。

相关问题