JDK11 HttpClient 双向 TLS

huangapple go评论112阅读模式
英文:

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 中:

  1. // 证书和密钥数据,假设是 X.509 pem 格式
  2. final byte[] publicData = your_cert_data; // -----BEGIN CERTIFICATE----- ...
  3. final byte[] privateData = your_key_data; // -----BEGIN PRIVATE KEY----- ...
  4. // 解析证书
  5. final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
  6. final Collection<? extends Certificate> chain = certificateFactory.generateCertificates(
  7. new ByteArrayInputStream(publicData));
  8. LOG.info("成功加载客户端证书链 {}", String.join(" -> ", chain
  9. .stream()
  10. .map(certificate -> {
  11. if (certificate instanceof X509Certificate) {
  12. final X509Certificate x509Cert = (X509Certificate) certificate;
  13. return x509Cert.getSubjectDN().toString();
  14. } else {
  15. return certificate.getType();
  16. }
  17. }).collect(Collectors.toList())));
  18. // 解析密钥
  19. final Key key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateData));
  20. // 将证书和密钥放入 KeyStore
  21. KeyStore clientKeyStore = KeyStore.getInstance("jks");
  22. final char[] pwdChars = KEYSTORE_PASSWORD.toCharArray(); // 使用随机字符串,例如从 java.security.SecureRandom 获取
  23. clientKeyStore.load(null, null);
  24. clientKeyStore.setKeyEntry(YOUR_SERVICE_NAME, key, pwdChars, chain.toArray(new Certificate[0]));
  25. // 初始化 KeyManagerFactory
  26. KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
  27. keyMgrFactory.init(clientKeyStore, pwdChars);
  28. // 使用密钥管理器填充 SSLContext
  29. SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
  30. sslCtx.init(keyMgrFactory.getKeyManagers(), null, null);

创建 SSL 参数,将 needClientAuth 设置为 true:

  1. SSLParameters sslParam = new SSLParameters();
  2. sslParam.setNeedClientAuth(true);

最后,创建 HttpClient:

  1. HttpClient client = HttpClient.newBuilder()
  2. .sslContext(sslCtx)
  3. .sslParameters(sslParam)
  4. .build();
英文:

Figured it out. Create an HttpClient, then pass in SSLContext and SSLParameters objects.

Load cert/key into SSLContext:

  1. // cert+key data. assuming X509 pem format
  2. final byte[] publicData = your_cert_data; // -----BEGIN CERTIFICATE----- ...
  3. final byte[] privateData = your_key_data; // -----BEGIN PRIVATE KEY----- ...
  4. // parse certificate
  5. final CertificateFactory certificateFactory = CertificateFactory.getInstance(&quot;X.509&quot;);
  6. final Collection&lt;? extends Certificate&gt; chain = certificateFactory.generateCertificates(
  7. new ByteArrayInputStream(publicData));
  8. LOG.info(&quot;Successfully loaded the client cert certificate chain {}&quot;, String.join(&quot; -&gt; &quot;, chain
  9. .stream()
  10. .map(certificate -&gt; {
  11. if (certificate instanceof X509Certificate) {
  12. final X509Certificate x509Cert = (X509Certificate) certificate;
  13. return x509Cert.getSubjectDN().toString();
  14. } else {
  15. return certificate.getType();
  16. }
  17. }).collect(Collectors.toList())));
  18. // parse key
  19. final Key key = KeyFactory.getInstance(&quot;RSA&quot;).generatePrivate(new PKCS8EncodedKeySpec(privateData));
  20. // place cert+key into KeyStore
  21. KeyStore clientKeyStore = KeyStore.getInstance(&quot;jks&quot;);
  22. final char[] pwdChars = KEYSTORE_PASSWORD.toCharArray(); // use a random string, like from java.security.SecureRandom
  23. clientKeyStore.load(null, null);
  24. clientKeyStore.setKeyEntry(YOUR_SERVICE_NAME, key, pwdChars, chain.toArray(new Certificate[0]));
  25. // initialize KeyManagerFactory
  26. KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance(&quot;SunX509&quot;);
  27. keyMgrFactory.init(clientKeyStore, pwdChars);
  28. // populate SSLContext with key manager
  29. SSLContext sslCtx = SSLContext.getInstance(&quot;TLSv1.2&quot;);
  30. sslCtx.init(keyMgrFactory.getKeyManagers(), null, null);

Create ssl parameters, set needClientAuth to true:

  1. SSLParameters sslParam = new SSLParameters();
  2. sslParam.setNeedClientAuth(true);

finally, create the HttpClient:

  1. HttpClient client = HttpClient.newBuilder()
  2. .sslContext(sslCtx)
  3. .sslParameters(sslParam)
  4. .build();

huangapple
  • 本文由 发表于 2020年7月22日 04:19:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/63022464.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定