java - HttpClient 始终采用 KeyStore 的第一个证书条目
问题描述
我有两个不同的 keyStoresservice1.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
now 仅与第一个一起成功service1
,而请求service2
变得未经授权。对我来说,我HttpClient
现在只需要第一个输入表common.jks
。如何HttpClient
为请求使用正确的别名?
解决方案
我相信这是默认行为。SSLContextBuilder 的 Javadocs 中有一条注释:
请注意:SSLContext.init(KeyManager[], TrustManager[], SecureRandom) 的默认 Oracle JSSE 实现接受多个密钥和信任管理器,但只使用第一个匹配类型。参见例如:SSLContext.html#init
许多 Java 库和框架都有这个问题——证书可以存储在带有别名的密钥库中,原则上,如果应用程序必须提供证书,它可以选择使用哪个别名。但是,执行此操作的工具通常从库中省略,假设应用程序永远不需要使用多个密钥库。
推荐阅读
- r - 如何从其 cdf 不是封闭形式的分布中生成数据?
- spring-boot - Spring Boot webflux - 验证配置属性
- google-sheets - 谷歌表格上流通股的历史数据
- elasticsearch - 使用 axios elasticsearch 发布 bulk.json
- html - 如何正确显示这个角度日历的日期?
- visual-studio-code - VS Code - 如何关闭自动启动
- tensorflow - 如果我使用 VRAM 不足的显卡训练大型深度学习模型会怎样?
- r - 如何手动匹配left_join不匹配的单元格?
- json - ' ' 类型的值没有下标 - JSON 数据
- javascript - 对象数组内对象数组的对象部分的模板内强制变化检测