Skip to content

Commit 6e627b9

Browse files
authored
bael 6549 - Using HTTPS with Jersey Client in Java (#18752)
1 parent 2b97ffa commit 6e627b9

File tree

3 files changed

+186
-0
lines changed

3 files changed

+186
-0
lines changed

web-modules/jersey-2/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@
115115
<artifactId>jakarta.xml.bind-api</artifactId>
116116
<version>${jaxb-runtime.version}</version> <!-- Or the latest version -->
117117
</dependency>
118+
<dependency>
119+
<groupId>org.wiremock</groupId>
120+
<artifactId>wiremock</artifactId>
121+
<version>${wiremock.version}</version>
122+
<scope>test</scope>
123+
</dependency>
118124
</dependencies>
119125

120126
<build>
@@ -144,6 +150,7 @@
144150
<jaxb-runtime.version>3.0.1</jaxb-runtime.version>
145151
<junit.jupiter.version>5.8.2</junit.jupiter.version>
146152
<mockito-junit-jupiter.version>4.5.1</mockito-junit-jupiter.version>
153+
<wiremock.version>3.13.0</wiremock.version>
147154
</properties>
148155

149156
</project>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package com.baeldung.jersey.https;
2+
3+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
4+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
5+
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
8+
import java.io.IOException;
9+
import java.nio.file.Paths;
10+
import java.security.KeyManagementException;
11+
import java.security.KeyStoreException;
12+
import java.security.NoSuchAlgorithmException;
13+
import java.security.UnrecoverableKeyException;
14+
import java.security.cert.CertificateException;
15+
16+
import javax.net.ssl.SSLContext;
17+
18+
import org.apache.hc.core5.ssl.SSLContextBuilder;
19+
import org.junit.jupiter.api.AfterEach;
20+
import org.junit.jupiter.api.Test;
21+
22+
import com.github.tomakehurst.wiremock.WireMockServer;
23+
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
24+
25+
import jakarta.ws.rs.client.Client;
26+
import jakarta.ws.rs.client.ClientBuilder;
27+
import jakarta.ws.rs.core.Response;
28+
29+
/**
30+
* 1. run {@code gen-keys.sh api.service} to generate server certificate/stores
31+
* 2. specify system properties with the directory of the certificates and password
32+
* 3. create api.service entries for 127.0.0.1 in /etc/hosts
33+
* 4. run this class
34+
*/
35+
class JerseyHttpsClientManualTest {
36+
37+
static final String MOCK_HOST = "api.service";
38+
static final String CERTS_DIR = System.getProperty("certs.dir");
39+
static final String PASSWORD = System.getProperty("certs.password");
40+
41+
WireMockServer api;
42+
43+
void setup(boolean mTls) {
44+
api = mockHttpsServer(mTls);
45+
api.stubFor(get(urlEqualTo("/test")).willReturn(aResponse().withHeader("Content-Type", "text/plain")
46+
.withStatus(200)
47+
.withBody("ok")));
48+
api.start();
49+
50+
System.out.println(">> Mock server started on HTTPS port: " + api.httpsPort());
51+
}
52+
53+
@AfterEach
54+
void teardown() {
55+
if (api != null) {
56+
api.stop();
57+
}
58+
}
59+
60+
@Test
61+
void whenUsingJVMParameters_thenCorrectCertificateUsed() {
62+
setup(false);
63+
64+
System.setProperty("javax.net.ssl.trustStore", CERTS_DIR + "/trust." + MOCK_HOST + ".p12");
65+
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
66+
67+
Response response = ClientBuilder.newClient().target(String.format("https://%s:%d/test", api.getOptions().bindAddress(), api.httpsPort()))
68+
.request()
69+
.get();
70+
71+
assertEquals(200, response.getStatus());
72+
}
73+
74+
@Test
75+
void whenUsingCustomSSLContext_thenCorrectCertificateUsed() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
76+
setup(false);
77+
78+
SSLContext sslContext = SSLContextBuilder.create()
79+
.loadTrustMaterial(Paths.get(CERTS_DIR + "/trust." + MOCK_HOST + ".p12"), PASSWORD.toCharArray())
80+
.build();
81+
82+
Client client = ClientBuilder.newBuilder()
83+
.sslContext(sslContext)
84+
.build();
85+
86+
Response response = client.target(String.format("https://%s:%d/test", api.getOptions().bindAddress(), api.httpsPort()))
87+
.request()
88+
.get();
89+
assertEquals(200, response.getStatus());
90+
}
91+
92+
@Test
93+
void whenUsingMutualTLS_thenCorrectCertificateUsed() throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
94+
setup(true);
95+
96+
char[] password = PASSWORD.toCharArray();
97+
98+
SSLContext sslContext = SSLContextBuilder.create()
99+
.loadTrustMaterial(Paths.get(CERTS_DIR + "/trust." + MOCK_HOST + ".p12"), password)
100+
.loadKeyMaterial(Paths.get(CERTS_DIR + "/client." + MOCK_HOST + ".p12"), password, password)
101+
.build();
102+
103+
Client client = ClientBuilder.newBuilder()
104+
.sslContext(sslContext)
105+
.build();
106+
107+
Response response = client.target(String.format("https://%s:%d/test", api.getOptions().bindAddress(), api.httpsPort()))
108+
.request()
109+
.get();
110+
assertEquals(200, response.getStatus());
111+
}
112+
113+
private static WireMockServer mockHttpsServer(boolean mTls) {
114+
WireMockConfiguration config = WireMockConfiguration.options()
115+
.bindAddress(MOCK_HOST)
116+
.dynamicPort()
117+
.dynamicHttpsPort()
118+
.keystorePath(CERTS_DIR + "/server." + MOCK_HOST + ".p12")
119+
.keystorePassword(PASSWORD)
120+
.keyManagerPassword(PASSWORD);
121+
122+
if (mTls) {
123+
config.trustStorePath(CERTS_DIR + "/trust." + MOCK_HOST + ".p12")
124+
.trustStorePassword(PASSWORD)
125+
.needClientAuth(true);
126+
}
127+
128+
return new WireMockServer(config);
129+
}
130+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/bash -e
2+
# @see JerseyHttpsClientManualTest
3+
# generates a CA, signed client/server keys and trust stores for the provided host.
4+
# e.g.: gen-keys.sh api.service <desired-password>
5+
MYSELF="$(readlink -f $0)"
6+
MYDIR="${MYSELF%/*}"
7+
8+
HOST=${1}
9+
if [[ -z "$HOST" ]]; then
10+
echo "arg 1 should be the host/alias"
11+
exit 1
12+
fi
13+
14+
PASSWORD="${2}"
15+
if [[ -z "$PASSWORD" ]]; then
16+
echo "arg 2 should be the desired password"
17+
exit 1
18+
fi
19+
20+
VALIDITY_DAYS=1
21+
CERTS_DIR=$MYDIR/keystore
22+
23+
mkdir -p "$CERTS_DIR"
24+
25+
keytool=$JAVA_HOME/bin/keytool
26+
$JAVA_HOME/bin/java -version
27+
28+
echo '1. creating certificate authority (CA)'
29+
openssl genrsa -out $CERTS_DIR/ca.${HOST}.key 2048
30+
openssl req -x509 -new -nodes -key $CERTS_DIR/ca.${HOST}.key -sha256 -days $VALIDITY_DAYS -out $CERTS_DIR/ca.${HOST}.crt -subj "/CN=${HOST}"
31+
32+
echo '2. generating server key and CSR'
33+
openssl genrsa -out $CERTS_DIR/server.${HOST}.key 2048
34+
openssl req -new -key $CERTS_DIR/server.${HOST}.key -out $CERTS_DIR/server.${HOST}.csr -subj "/CN=${HOST}"
35+
openssl x509 -req -in $CERTS_DIR/server.${HOST}.csr -CA $CERTS_DIR/ca.${HOST}.crt -CAkey $CERTS_DIR/ca.${HOST}.key -CAcreateserial -out $CERTS_DIR/server.${HOST}.crt -days $VALIDITY_DAYS -sha256
36+
37+
echo '3. generating client key and CSR'
38+
openssl genrsa -out $CERTS_DIR/client.${HOST}.key 2048
39+
openssl req -new -key $CERTS_DIR/client.${HOST}.key -out $CERTS_DIR/client.${HOST}.csr -subj "/CN=${HOST}"
40+
openssl x509 -req -in $CERTS_DIR/client.${HOST}.csr -CA $CERTS_DIR/ca.${HOST}.crt -CAkey $CERTS_DIR/ca.${HOST}.key -CAcreateserial -out $CERTS_DIR/client.${HOST}.crt -days $VALIDITY_DAYS -sha256
41+
42+
echo '4. creating PKCS12 keystores'
43+
openssl pkcs12 -export -out $CERTS_DIR/server.${HOST}.p12 -inkey $CERTS_DIR/server.${HOST}.key -in $CERTS_DIR/server.${HOST}.crt -certfile $CERTS_DIR/ca.${HOST}.crt -name ${HOST} -passout pass:$PASSWORD
44+
openssl pkcs12 -export -out $CERTS_DIR/client.${HOST}.p12 -inkey $CERTS_DIR/client.${HOST}.key -in $CERTS_DIR/client.${HOST}.crt -certfile $CERTS_DIR/ca.${HOST}.crt -name ${HOST} -passout pass:$PASSWORD
45+
46+
echo '5. creating truststore'
47+
$keytool -importcert -keystore $CERTS_DIR/trust.${HOST}.p12 -storetype PKCS12 -storepass $PASSWORD -alias ca.${HOST} -file $CERTS_DIR/ca.${HOST}.crt -noprompt
48+
49+
echo done

0 commit comments

Comments
 (0)