微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

HttpClient始终采用KeyStore形式的第一个证书输入

如何解决HttpClient始终采用KeyStore形式的第一个证书输入

我分别为两个不同的服务有两个不同的密钥库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();
  }

我只需要在项目中使用一个共享的keyStore。因此,我将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,Certificate fingerprint (SHA-256): 
...

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

解决方法

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

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

许多Java库和框架都存在此问题-证书可以使用别名存储在密钥库中,并且原则上,如果必须提供证书,则应用程序可以选择要使用的别名。但是,假设应用程序永远不需要使用多个密钥库,就常常会从库中忽略执行此操作的功能。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。