Skip to content

Commit 1729927

Browse files
Merge pull request #18702 from amit88265/BAEL-8591
BAEL-8591 added code for mTLS calls with Java Client
2 parents 5e893cd + d85489b commit 1729927

File tree

7 files changed

+251
-0
lines changed

7 files changed

+251
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.baeldung.mtls.calls;
2+
3+
import javax.net.ssl.HostnameVerifier;
4+
5+
public class HostNameVerifierBuilder {
6+
7+
static HostnameVerifier allHostsValid = (hostname, session) -> true;
8+
9+
public static HostnameVerifier getAllHostsValid() {
10+
return allHostsValid;
11+
}
12+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.baeldung.mtls.calls;
2+
3+
import java.io.ByteArrayInputStream;
4+
import java.io.IOException;
5+
import java.nio.charset.Charset;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.security.Key;
9+
import java.security.KeyFactory;
10+
import java.security.KeyManagementException;
11+
import java.security.KeyStore;
12+
import java.security.KeyStoreException;
13+
import java.security.NoSuchAlgorithmException;
14+
import java.security.UnrecoverableKeyException;
15+
import java.security.cert.Certificate;
16+
import java.security.cert.CertificateException;
17+
import java.security.cert.CertificateFactory;
18+
import java.security.cert.X509Certificate;
19+
import java.security.spec.InvalidKeySpecException;
20+
import java.security.spec.PKCS8EncodedKeySpec;
21+
import java.util.Base64;
22+
import java.util.Collection;
23+
import java.util.Properties;
24+
25+
import javax.net.ssl.KeyManagerFactory;
26+
import javax.net.ssl.SSLContext;
27+
import javax.net.ssl.TrustManager;
28+
import javax.net.ssl.X509TrustManager;
29+
30+
public class SslContextBuilder {
31+
32+
public static SSLContext buildSslContext()
33+
throws IOException, CertificateException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException,
34+
KeyManagementException {
35+
final Properties props = System.getProperties();
36+
props.setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString());
37+
38+
String privateKeyPath = "src/main/resources/keys/client.key.pkcs8";
39+
String publicKeyPath = "src/main/resources/keys/client.crt";
40+
41+
final byte[] publicData = Files.readAllBytes(Path.of(publicKeyPath));
42+
final byte[] privateData = Files.readAllBytes(Path.of(privateKeyPath));
43+
44+
String privateString = new String(privateData, Charset.defaultCharset()).replace("-----BEGIN PRIVATE KEY-----", "")
45+
.replaceAll(System.lineSeparator(), "")
46+
.replace("-----END PRIVATE KEY-----", "");
47+
48+
byte[] encoded = Base64.getDecoder()
49+
.decode(privateString);
50+
51+
final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
52+
final Collection<? extends Certificate> chain = certificateFactory.generateCertificates(new ByteArrayInputStream(publicData));
53+
54+
Key key = KeyFactory.getInstance("RSA")
55+
.generatePrivate(new PKCS8EncodedKeySpec(encoded));
56+
57+
KeyStore clientKeyStore = KeyStore.getInstance("jks");
58+
final char[] pwdChars = "test".toCharArray();
59+
clientKeyStore.load(null, null);
60+
clientKeyStore.setKeyEntry("test", key, pwdChars, chain.toArray(new Certificate[0]));
61+
62+
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
63+
keyManagerFactory.init(clientKeyStore, pwdChars);
64+
65+
TrustManager[] acceptAllTrustManager = { new X509TrustManager() {
66+
public X509Certificate[] getAcceptedIssuers() {
67+
return new X509Certificate[0];
68+
}
69+
70+
public void checkClientTrusted(X509Certificate[] certs, String authType) {
71+
}
72+
73+
public void checkServerTrusted(X509Certificate[] certs, String authType) {
74+
}
75+
} };
76+
SSLContext sslContext = SSLContext.getInstance("TLS");
77+
sslContext.init(keyManagerFactory.getKeyManagers(), acceptAllTrustManager, new java.security.SecureRandom());
78+
return sslContext;
79+
}
80+
81+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIID8zCCAdugAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA8qLnlv
3+
dXIuaG9zdG5hbWUwHhcNMjUwNzA3MTY0NTMzWhcNMjYwNzA3MTY0NTMzWjAcMRow
4+
GAYDVQQDDBEqLmNsaWVudC5ob3N0bmFtZTCCASIwDQYJKoZIhvcNAQEBBQADggEP
5+
ADCCAQoCggEBAKavVV7T7MEWY2pVUSWzIGfaVqSEBgKmdUJWnNGHwZrBX/XjJ9LN
6+
srBAOjT/mJ4ccoMTKY8agDmF7z0nz8fQSr5D4JQ6C1yBbjKL04BwLSrNIRPIzWrb
7+
F4ztADOrrh1l3YaRYbwMWkFZjcoRX9zXYooMbZPrgBSskQ8hdnrIMtc04+FvFhyP
8+
5hEtqvR9I8qGjxGx/wXAYA539Owh9T3Xl0vVroxtv2eFNYIIg7BV1yHrX1RalEbx
9+
5mzfeM7o/IJRvj/73jVhdvu2csUM4J20NxSx1B9XoFZI8Y0JPOR4bo3j7zZXE0iH
10+
ib6/pWYxdZknWDsm7qHTLZJNEFPNk/W2/0UCAwEAAaNCMEAwHQYDVR0OBBYEFOkk
11+
ZcxKbJpkiG0Mr5ce/6ykH9rGMB8GA1UdIwQYMBaAFARhDN6rdEw0ylzmwgVRXUbO
12+
BNmJMA0GCSqGSIb3DQEBCwUAA4ICAQAGPhAPinkHWHfSiQRChtxEAnTPVavsuC6X
13+
UyGGpWHz7OD475SbzYnuaTN+O/2HUoP3qyVWH8igSOLBY1vpUXthkSHBltH21Gog
14+
NFW4Z4/8NBlvM25BiBA/hGANFu5MvWuB9gNfHryWSZHFf0fyOd7ITIY2pDUHkqlc
15+
e5pAkjGAlvATGeF8PcMzYDAF6DamtJVZtqha/ssAGPlDggbr55LqtKos9TphYGsN
16+
LOnWv+f81TB8euLUTJpFg4i+t5QGmQ1UWv2N1U4TEo5fpRb+y6E/vorUH4qpDKOn
17+
31mvjxkgW05Jf21GKQU5LtYIfR3ZVa7UlWkdr9x763pzNUB0q8ioPQ2jQ3bzrJEO
18+
El3dhiWCUAXGxljKWeuUwkdws3D4mOru6hVwE7vE31ZD3mnO52uOtwd6sKeGg7zj
19+
OgTu06/KSbYEVsZ1yic8CWVSR2Sn+4HtXo7cEuBCnWJIkqRNGoFTbKULaSWLN+Lh
20+
wzTIcBA6E5SoHXY0T80EsVQAq2LV7bymDklHeBWUMr47guUUyBsoZg36njA7geT5
21+
T8dIeyClWHZNwqa8kxbQt6WAY21qqUyovsn0js26Ni8sr3iv+akXZkeJGopgYV4g
22+
BNMow0BNLsKLRhDM0gkIqlOwHMRIYwsdNkrSk4mnZoxlGIotVb4JCAazxss5rJR2
23+
IVboXKO91g==
24+
-----END CERTIFICATE-----
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmr1Ve0+zBFmNq
3+
VVElsyBn2lakhAYCpnVCVpzRh8GawV/14yfSzbKwQDo0/5ieHHKDEymPGoA5he89
4+
J8/H0Eq+Q+CUOgtcgW4yi9OAcC0qzSETyM1q2xeM7QAzq64dZd2GkWG8DFpBWY3K
5+
EV/c12KKDG2T64AUrJEPIXZ6yDLXNOPhbxYcj+YRLar0fSPKho8Rsf8FwGAOd/Ts
6+
IfU915dL1a6Mbb9nhTWCCIOwVdch619UWpRG8eZs33jO6PyCUb4/+941YXb7tnLF
7+
DOCdtDcUsdQfV6BWSPGNCTzkeG6N4+82VxNIh4m+v6VmMXWZJ1g7Ju6h0y2STRBT
8+
zZP1tv9FAgMBAAECggEAC5oBjaeff3MA+Wo1yzN0CnZyeGHuDyop2DOyF41k5tIV
9+
zUYBxBToHodh5cVyiHK/b6saRekYyqgtViratfQj96k+zOJbXxVtJ5x+3J4yLpv3
10+
dOqRjaHxOjBWxsHozQgFirO8wzty3sCOc2WRMAxXwfcKe3S1Rfsa35w7JGGh1EOv
11+
ygOACa+9iLsT8iAVGtmaFybp3wNFS+MYibe/v7qhM1MLktGJH8tZIzYr87iLP7uF
12+
6WZve1/QCvNwyvKsdSYIvNzaVYJTuWacTVKaANmEci5TYtQzFVQScX9PdrdNtQdu
13+
2pxtbI0Y8oT04KXQ0Bsnejc5ckE/pzgIzB17lF+O0QKBgQDhIZ48YxaRWN1JEsii
14+
zvzcEz3hMKBzZ//oFB0/tb4AFuIrMaeoVZf0jH571KWO9BV+ExxCBIROr7twdIxk
15+
OfwCGN4034+hJlBxrBSf8lN3jYHV6t1xBniz1PkoUjUI+RzjoPY9T0hsYUv76vcZ
16+
2uqgCCXlu2Ssj+MPRkeH2laXyQKBgQC9iizU1NiHgwxL7TVf9Wiz7wxC/UWe9/32
17+
EZyFS83GIJffLXowQA997qWa/NtbcP+Dpdm6vbYbW6FBRE7EH6zQgLWZtollmuaR
18+
cmCXzSmB84P5wz8fF0o8HZnjzMiM4Dm8pUXlNj/05QUGBT+4YG5pKKqR5RLj3rXE
19+
i4eUaDMhnQKBgQClZ2OwjkSIaTe7dld+doEE2AZAqs9XuvMjeZO7uTVtL2LfxU2e
20+
ubQ48fgD1soEa4RW6od6YYMrpKUcDCURhiCHEepAAniuN04nFfzZPtrgHVFk73fe
21+
kJih1zlvzGY2v3/gJeSESvm01w9SeOEvV83F4famALYIqnZyRHpNb7brMQKBgQCp
22+
bBp4wC0wrEZQlB9SwBWwSOyH8MbLu1bKHqHvUHwGLtoyRv9io9B1O93R9VXKne33
23+
6kb+MlfWiohQw9M4YiviUDqDxPN53AVfW4LWDjCdFWQR3KHOk83qgHcvdbyKmF9j
24+
rcQVh/GRYSmlYQm9MI1g+FXHhaDmCQwnPKWbVazmzQKBgHV3r3ahlszePYHQmQLr
25+
4eJM7Kj3Y0SydM3402TLH8DG4CeuOkO+/ZhHAE3AgAzQptOqbZ25/RS+7O6N+Wa1
26+
Lo6kbrSgoqQgqzyHrp3PcWeJ1n/mef0QxbV/fKWWfdzFRtA2oTwXteW3Dzmu7A84
27+
65QBcsuKKf34GJfvwl8eQT/O
28+
-----END PRIVATE KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.baeldung.mtls.calls;
2+
3+
import java.io.IOException;
4+
import java.net.URI;
5+
import java.net.http.HttpClient;
6+
import java.net.http.HttpRequest;
7+
import java.net.http.HttpResponse;
8+
import java.security.KeyManagementException;
9+
import java.security.KeyStoreException;
10+
import java.security.NoSuchAlgorithmException;
11+
import java.security.UnrecoverableKeyException;
12+
import java.security.cert.CertificateException;
13+
import java.security.spec.InvalidKeySpecException;
14+
15+
import javax.net.ssl.SSLContext;
16+
17+
import org.assertj.core.api.Assertions;
18+
import org.junit.Test;
19+
20+
public class MutualTLSCallWithHttpClientLiveTest {
21+
22+
@Test
23+
public void whenWeExecuteMutualTLSCallToNginxServerWithHttpClient_thenItShouldReturnStatusOK()
24+
throws UnrecoverableKeyException, CertificateException, IOException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException,
25+
KeyManagementException {
26+
SSLContext sslContext = SslContextBuilder.buildSslContext();
27+
HttpClient client = HttpClient.newBuilder()
28+
.sslContext(sslContext)
29+
.build();
30+
31+
HttpRequest exactRequest = HttpRequest.newBuilder()
32+
.uri(URI.create("https://localhost/ping"))
33+
.GET()
34+
.build();
35+
36+
HttpResponse<String> response = client.sendAsync(exactRequest, HttpResponse.BodyHandlers.ofString())
37+
.join();
38+
Assertions.assertThat(response)
39+
.isNotNull();
40+
Assertions.assertThat(response.statusCode())
41+
.isEqualTo(200);
42+
}
43+
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.baeldung.mtls.calls;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.net.URL;
6+
import java.nio.charset.Charset;
7+
import java.security.KeyManagementException;
8+
import java.security.KeyStoreException;
9+
import java.security.NoSuchAlgorithmException;
10+
import java.security.UnrecoverableKeyException;
11+
import java.security.cert.CertificateException;
12+
import java.security.spec.InvalidKeySpecException;
13+
14+
import javax.net.ssl.HttpsURLConnection;
15+
import javax.net.ssl.SSLContext;
16+
17+
import org.assertj.core.api.Assertions;
18+
import org.junit.Test;
19+
20+
public class MutualTLSCallWithHttpURLConnectionLiveTest {
21+
22+
@Test
23+
public void whenWeExecuteMutualTLSCallToNginxServerWithHttpURLConnection_thenItShouldReturnNonNullResponse()
24+
throws UnrecoverableKeyException, CertificateException, IOException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException,
25+
KeyManagementException {
26+
SSLContext sslContext = SslContextBuilder.buildSslContext();
27+
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) new URL("https://127.0.0.1/ping").openConnection();
28+
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
29+
httpsURLConnection.setHostnameVerifier(HostNameVerifierBuilder.getAllHostsValid());
30+
InputStream inputStream = httpsURLConnection.getInputStream();
31+
String response = new String(inputStream.readAllBytes(), Charset.defaultCharset());
32+
Assertions.assertThat(response)
33+
.isNotNull();
34+
}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.baeldung.mtls.calls;
2+
3+
import java.io.IOException;
4+
import java.security.KeyManagementException;
5+
import java.security.KeyStoreException;
6+
import java.security.NoSuchAlgorithmException;
7+
import java.security.UnrecoverableKeyException;
8+
import java.security.cert.CertificateException;
9+
import java.security.spec.InvalidKeySpecException;
10+
11+
import javax.net.ssl.SSLContext;
12+
13+
import org.assertj.core.api.Assertions;
14+
import org.junit.Test;
15+
16+
public class SslContextBuilderUnitTest {
17+
18+
@Test
19+
public void whenPrivateAndPublicKeysAreGiven_thenAnSSLContextShouldBeCreated()
20+
throws UnrecoverableKeyException, CertificateException, IOException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException,
21+
KeyManagementException {
22+
SSLContext sslContext = SslContextBuilder.buildSslContext();
23+
Assertions.assertThat(sslContext)
24+
.isNotNull();
25+
}
26+
}

0 commit comments

Comments
 (0)