Skip to content

Instantly share code, notes, and snippets.

@fzakaria
Last active October 20, 2022 10:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fzakaria/c94db498a479ee1711f571cad2776b34 to your computer and use it in GitHub Desktop.
Save fzakaria/c94db498a479ee1711f571cad2776b34 to your computer and use it in GitHub Desktop.
How to properly use an http client with a self signed certificate
/**
* Too many examples on the internet demonstrate using self-signed certificates by disabling hostname verification
or providing a weak TrustManager (i.e. SelfSignedTrustManager).
This example shows how to properly start a server & client in the same JVM where the client knows about the
generated self-signed certificate.
Also it's all done programmatically! Avoid using keytool and pulling in heavy dependencies like BouncyCastle!~
**/
public class SecureServerTest {
/**
* Use netty to create a self signed certificate easily.
If you don't use netty you can easily make one similarily using the JDK
private static final SelfSignedCertificate SELF_SIGNED_CERTIFICATE = uncheckedSelfSignedCertificate("localhost");
/**
* Load the self-signed certificate into a KeyStore
*/
private static final KeyStore KEY_STORE_WITH_SELF_SIGNED = loadSelfSignedCertificate(SELF_SIGNED_CERTIFICATE);
private static final HttpServerOptions TEST_OPTIONS =
HttpServerOptions.builder().withPrivateKeyAndCertificate(SELF_SIGNED_CERTIFICATE.key(), SELF_SIGNED_CERTIFICATE.cert())
.build();
@Test
public void testServerWithSSL() throws Exception {
/**
* This example uses Apache HttpClient however it would be similar for other clients.
Load the trust store we created that knows about our self-signed certificate.
*/
final SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(KEY_STORE_WITH_SELF_SIGNED, null)
.build();
/* Create the server with SSL mode enabled with whatever framework you are using. */
try (HttpServer server = HttpServer.listen(0, TEST_OPTIONS)) {
/* Set the SSLContext for Apache's httpClient */
try (CloseableHttpClient client = HttpClientBuilder.create().setSSLContext(sslContext).build()) {
/* Unirest is just a simple fluent wrapper over Apache's http client. */
Unirest.setHttpClient(client);
String url = String.format("https://localhost:%s", server.getPort());
com.mashape.unirest.http.HttpResponse<String> response = Unirest.get(url).asString();
Assertions.assertThat(response.getStatus()).isEqualTo(200);
}
}
}
private static SelfSignedCertificate uncheckedSelfSignedCertificate(String fqdn) {
try {
return new SelfSignedCertificate(fqdn);
} catch (CertificateException e) {
throw new RuntimeException(e);
}
}
private static KeyStore loadSelfSignedCertificate(SelfSignedCertificate certificate) {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("localhost", certificate.cert());
return keyStore;
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment