HttpClient 始终采用第一个证书条目形式 KeyStore
HttpClient takes always the first certificate entry form KeyStore
我有两个不同的 keyStores service1.jks
和 sevice2.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.jks
和 sevice2.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 文档中有一个 note:
Please note: the default Oracle JSSE implementation of
SSLContext.init(KeyManager[], TrustManager[], SecureRandom) accepts
multiple key and trust managers, however only only first matching type
is ever used. See for example: SSLContext.html#init
许多 Java 库和框架都有这个问题——证书可以用别名存储在密钥库中,原则上,应用程序可以 select 如果必须使用哪个别名出示证书。但是,库通常忽略了执行此操作的工具,假设应用程序永远不需要使用多个密钥库。
我有两个不同的 keyStores service1.jks
和 sevice2.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.jks
和 sevice2.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 文档中有一个 note:
Please note: the default Oracle JSSE implementation of SSLContext.init(KeyManager[], TrustManager[], SecureRandom) accepts multiple key and trust managers, however only only first matching type is ever used. See for example: SSLContext.html#init
许多 Java 库和框架都有这个问题——证书可以用别名存储在密钥库中,原则上,应用程序可以 select 如果必须使用哪个别名出示证书。但是,库通常忽略了执行此操作的工具,假设应用程序永远不需要使用多个密钥库。