英文:
JDK11 HttpClient mutual tls
问题
我正在寻求使用Java 11提供的新HttpClient。目前不清楚如何进行双向TLS(双方认证,即客户端和服务器都提供证书)。
是否能提供一个使用HttpClient进行双向TLS的示例?
英文:
I'm looking to use the new HttpClient provided in java 11. It's not clear how to do mutual TLS (2 way auth, where both client and server present a certificate.)
Could someone provide an example of mutual TLS with HttpClient?
答案1
得分: 16
弄清楚了。创建一个 HttpClient,然后传入 SSLContext 和 SSLParameters 对象。
将证书/密钥加载到 SSLContext 中:
// 证书和密钥数据,假设是 X.509 pem 格式
final byte[] publicData = your_cert_data; // -----BEGIN CERTIFICATE----- ...
final byte[] privateData = your_key_data; // -----BEGIN PRIVATE KEY----- ...
// 解析证书
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
final Collection<? extends Certificate> chain = certificateFactory.generateCertificates(
new ByteArrayInputStream(publicData));
LOG.info("成功加载客户端证书链 {}", 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())));
// 解析密钥
final Key key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateData));
// 将证书和密钥放入 KeyStore
KeyStore clientKeyStore = KeyStore.getInstance("jks");
final char[] pwdChars = KEYSTORE_PASSWORD.toCharArray(); // 使用随机字符串,例如从 java.security.SecureRandom 获取
clientKeyStore.load(null, null);
clientKeyStore.setKeyEntry(YOUR_SERVICE_NAME, key, pwdChars, chain.toArray(new Certificate[0]));
// 初始化 KeyManagerFactory
KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
keyMgrFactory.init(clientKeyStore, pwdChars);
// 使用密钥管理器填充 SSLContext
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();
英文:
Figured it out. Create an HttpClient, then pass in SSLContext and SSLParameters objects.
Load cert/key into 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);
Create ssl parameters, set needClientAuth to true:
SSLParameters sslParam = new SSLParameters();
sslParam.setNeedClientAuth(true);
finally, create the HttpClient:
HttpClient client = HttpClient.newBuilder()
.sslContext(sslCtx)
.sslParameters(sslParam)
.build();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论