【问题标题】:HttpClient takes always the first certificate entry form KeyStoreHttpClient 始终采用 KeyStore 的第一个证书条目
【发布时间】:2020-09-08 10:52:15
【问题描述】:

我有两个不同的 keyStores service1.jkssevice2.jks 对应于两个不同的服务(但它们具有相同的 RootSertificate)。这是我的httpClient,它可以成功地与这两种服务一起使用:

  public HttpClient getHttpClient(String filePath, String password) {
    KeyStore keyStore = KeyStore.getInstance(new File(filePath), password.toCharArray());

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

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

    return HttpClients.custom()
            .setSSLSocketFactory(socketFactory)
            .build();
  }

我只需要在我的项目中使用一个共享密钥库。所以我将service1.jkssevice2.jks 合并为一个通用的keyStore common.jks

cp sevice2.jks common.jks
keytool -importkeystore -srckeystore service1.jks -srcstoretype jks -srcstorepass changeit -destkeystore common.jks -deststoretype jks -deststorepass changeit

所以common.jks 有两个项目:

$ keytool -list -storepass changeit -keystore server.keystore.jks
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 2 entries

service1-alias, 8 сент. 2020 г., PrivateKeyEntry,
Certificate fingerprint (SHA-256): 
....
service2-alias, 8 сент. 2020 г., PrivateKeyEntry,
Certificate fingerprint (SHA-256): 
...

然后事实证明,我的 HttpClient 现在只能与第一个 service1 一起成功运行,而对 service2 的请求则未经授权。在我看来,我的HttpClient 现在只采用第一个输入表单common.jks。如何让HttpClient 为请求使用正确的别名?

【问题讨论】:

  • 更重要的是,为什么你有两个证书?两个身份?这里出了点问题。
  • 我相信这是默认行为。 SSLContextBuilder 的 Java 文档中有一条注释:“请注意:SSLContext.init(KeyManager[], TrustManager[], SecureRandom) 的默认 Oracle JSSE 实现接受多个密钥和信任管理器,但是只使用过第一个匹配类型. 参见例如:SSLContext.html#init"
  • @Marquis of Lorne - 我有两个证书,因为我有两个不同的服务。所以我的想法是拥有一个httpClient 和一个通用密钥库。
  • @Kevin Boone 你能把这个作为答案吗?
  • 您的主机可能有两个不同的服务,但它没有两个不同的身份。您不需要证书来识别服务。

标签: java ssl openssl keystore keytool


【解决方案1】:

我相信这是默认行为。 SSLContextBuilder 的 Javadocs 中有一个 note

请注意:默认的 Oracle JSSE 实现 SSLContext.init(KeyManager[], TrustManager[], SecureRandom) 接受 多个密钥和信任管理器,但只有第一个匹配类型 曾经使用过。参见例如:SSLContext.html#init

许多 Java 库和框架都有这个问题——证书可以使用别名存储在密钥库中,原则上,如果应用程序必须提供证书,则可以选择使用哪个别名。但是,执行此操作的工具通常从库中省略,假设应用程序永远不需要使用多个密钥库。

【讨论】:

  • Java 中有一种从密钥库中选择自定义别名的好方法。请参阅此问题stackoverflow.com/questions/15201251/… 和@Bruno 的答案。我现在正在为我的应用程序使用这种方法并且它有效。
猜你喜欢
  • 1970-01-01
  • 2015-11-06
  • 1970-01-01
  • 2015-02-14
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
  • 1970-01-01
相关资源
最近更新 更多