Я хочу использовать новый HttpClient, представленный в Java 11. Непонятно, как сделать взаимный TLS (двухсторонняя аутентификация, когда и клиент, и сервер представляют сертификат.)
Может ли кто-нибудь привести пример взаимного TLS с HttpClient?
Я хочу использовать новый HttpClient, представленный в Java 11. Непонятно, как сделать взаимный TLS (двухсторонняя аутентификация, когда и клиент, и сервер представляют сертификат.)
Может ли кто-нибудь привести пример взаимного TLS с HttpClient?
Догадаться. Создайте HttpClient, затем передайте объекты SSLContext и SSLParameters.
Загрузите сертификат/ключ в SSLContext:
// cert+key data. assuming X509 pem format
final byte[] publicData = your_cert_data; // -----BEGIN CERTIFICATE----- ...
final byte[] privateData = your_key_data; // -----BEGIN PRIVATE KEY----- ...
// parse certificate
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
final Collection<? extends Certificate> chain = certificateFactory.generateCertificates(
new ByteArrayInputStream(publicData));
LOG.info("Successfully loaded the client cert certificate chain {}", String.join(" -> ", chain
.stream()
.map(certificate -> {
if (certificate instanceof X509Certificate) {
final X509Certificate x509Cert = (X509Certificate) certificate;
return x509Cert.getSubjectDN().toString();
} else {
return certificate.getType();
}
}).collect(Collectors.toList())));
// parse key
final Key key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateData));
// place cert+key into KeyStore
KeyStore clientKeyStore = KeyStore.getInstance("jks");
final char[] pwdChars = KEYSTORE_PASSWORD.toCharArray(); // use a random string, like from java.security.SecureRandom
clientKeyStore.load(null, null);
clientKeyStore.setKeyEntry(YOUR_SERVICE_NAME, key, pwdChars, chain.toArray(new Certificate[0]));
// initialize KeyManagerFactory
KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
keyMgrFactory.init(clientKeyStore, pwdChars);
// populate SSLContext with key manager
SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
sslCtx.init(keyMgrFactory.getKeyManagers(), null, null);
Создайте параметры ssl, установите для needClientAuth значение true:
SSLParameters sslParam = new SSLParameters();
sslParam.setNeedClientAuth(true);
наконец, создайте HttpClient:
HttpClient client = HttpClient.newBuilder()
.sslContext(sslCtx)
.sslParameters(sslParam)
.build();
sslCtx.init(keyMgrFactory.getKeyManagers(), null, null);
- вы передаете менеджер нулевого доверия. это действительно то, что вы хотите?
- person Eugene; 24.07.2020
TrustManager
(в отличие от null/default
), иначе я всегда получал бы ошибку рукопожатия. Мои знания в этой области каким-то образом ограничены, поэтому мне было интересно, не могли бы вы пролить свет... Я получил закрытый ключ и сертификат клиента в pem-файле, и единственный способ подключения был через пустой менеджер доверия вместо ноль, который в лучшем случае выглядит так, будто я сделал что-то подозрительное.
- person Eugene; 25.07.2020
final Key key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateData));
не работает для закодированного ключа X.509, который предполагается в первых строках этого фрагмента.
- person Krzysztof Krasoń; 03.10.2020