如何配置 apache httpclient 4.5+ SSLContext 以使用带有自签名证书的双向 TLS 身份验证?
How to configure apache httpclient 4.5+ SSLContext to use mutual TLS authentication with a self signed certificate?
我正在尝试使用双向 TLS 身份验证从 httpclient 4.5 配置 CloseableHttpClient
。服务器证书是自签名的。
这是我使用的代码(灵感来自各种 Whosebug 帖子):
KeyStore trustStore = KeyStore.getInstance("pkcs12");
try (InputStream fis = new FileInputStream(ssl_cert_file)) {
trustStore.load(fis, password.toCharArray());
}
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(trustStore, password.toCharArray(), (map, socket) -> "client")
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.build();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier());
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", socketFactory).build();
connectionManager = new PoolingHttpClientConnectionManager(registry);
我得到了
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
我认为我提供的 CA 证书似乎没有被使用。
知道哪里出了问题吗?
CA的证书、客户端的证书和客户端的私钥在一个pkcs12文件中
用
生成
openssl pkcs12 -export -in client-cert.pem -inkey private/client-key.pem -certfile cacert.pem -name "client" -out client-cert.p12
我尝试 openssl s_client
检查证书 return 预期的输出(确实如此)。我怀疑问题出在我的代码而不是 client-cert.p12
文件。
openssl s_client -connect host:port -tls1 -cert client-cert.pem -key private/client-key.pem -CAfile cacert.pem
正如@Gimby 所指出的问题是我的 CA 证书在我的密钥库中未被识别为 TrustCertEntry。
我的解决方法是只为 CA 的证书生成一个 jks 文件:
keytool -import -alias client -file cacert.pem -storetype JKS -keystore cacert.jks
从中构建一个 KeyStore 对象并将其用于 SSLContext.loadTrustMaterial
。
我正在尝试使用双向 TLS 身份验证从 httpclient 4.5 配置 CloseableHttpClient
。服务器证书是自签名的。
这是我使用的代码(灵感来自各种 Whosebug 帖子):
KeyStore trustStore = KeyStore.getInstance("pkcs12");
try (InputStream fis = new FileInputStream(ssl_cert_file)) {
trustStore.load(fis, password.toCharArray());
}
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(trustStore, password.toCharArray(), (map, socket) -> "client")
.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.build();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier());
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", socketFactory).build();
connectionManager = new PoolingHttpClientConnectionManager(registry);
我得到了
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
我认为我提供的 CA 证书似乎没有被使用。 知道哪里出了问题吗?
CA的证书、客户端的证书和客户端的私钥在一个pkcs12文件中 用
生成openssl pkcs12 -export -in client-cert.pem -inkey private/client-key.pem -certfile cacert.pem -name "client" -out client-cert.p12
我尝试 openssl s_client
检查证书 return 预期的输出(确实如此)。我怀疑问题出在我的代码而不是 client-cert.p12
文件。
openssl s_client -connect host:port -tls1 -cert client-cert.pem -key private/client-key.pem -CAfile cacert.pem
正如@Gimby 所指出的问题是我的 CA 证书在我的密钥库中未被识别为 TrustCertEntry。
我的解决方法是只为 CA 的证书生成一个 jks 文件:
keytool -import -alias client -file cacert.pem -storetype JKS -keystore cacert.jks
从中构建一个 KeyStore 对象并将其用于 SSLContext.loadTrustMaterial
。