javaspring-bootsslapache-httpclient-4.x

Adding .pem files to Apache HttpClient


I need to add these 3 pem files (ca.pem, key.pem, and cert.pem) to my http client in order to access a client's service.

How do I get these to work with my existing httpclient? Any help will be appreciated.

Thank you.


File caFile = new File(getClass().getResource("/certs/ca.pem").getPath());
File keyFile = new File(getClass().getResource("/certs/key.pem").getPath());
File certFile = new File(getClass().getResource("/certs/cert.pem").getPath());


SSLContext sslContext = new SSLContextBuilder()
            .loadTrustMaterial(null, ( certificate, authType ) -> true).build();

CloseableHttpClient httpClient = HttpClients.custom()
            .setSSLContext(sslContext)
            .setSSLHostnameVerifier(new NoopHostnameVerifier())
            .addInterceptorFirst((HttpRequestInterceptor) ( httpRequest, httpContext ) -> {
                httpRequest.setHeader("Content-Type", "application/xml");
            })
            .build();

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);

Solution

  • I have guided the OP and provided the answer in the comment section of his question. The solution did work, so I am posting it here.

    Java is limited and verbose of handling all of the different pem files. In the past I wanted also to load pem files for different projects and to make it reusable I created a library which does the trick. The solution which I provided to the OP for an apache http client is:

    Option 1

    You first need to add the following dependency GitHub - SSLContext Kickstart:

    <dependency>
        <groupId>io.github.hakky54</groupId>
        <artifactId>sslcontext-kickstart-for-pem</artifactId>
        <version>8.0.0</version>
    </dependency>
    

    And then you can use the following code snippet:

    import nl.altindag.ssl.SSLFactory;
    import nl.altindag.ssl.pem.util.PemUtils;
    import org.apache.http.client.HttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    
    import javax.net.ssl.X509ExtendedKeyManager;
    import javax.net.ssl.X509ExtendedTrustManager;
    
    public class App {
    
        public static void main(String[] args) {
            X509ExtendedKeyManager keyManager = PemUtils.loadIdentityMaterial("certs/cert.pem", "certs/key.pem");
            X509ExtendedTrustManager trustManager = PemUtils.loadTrustMaterial("certs/ca.pem");
    
            SSLFactory sslFactory = SSLFactory.builder()
                    .withIdentityMaterial(keyManager)
                    .withTrustMaterial(trustManager)
                    .build();
    
            HttpClient httpclient = HttpClients.custom()
                    .setSSLContext(sslFactory.getSslContext())
                    .build();
    
            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
            requestFactory.setHttpClient(httpclient);
        }
        
    }
    

    Option 2

    If you don't want the above library and you don't have an encrypted private keys and just certificates as pem files, then you can also give the following example from another answer a try: https://stackoverflow.com/a/42733858/6777695 That one provides an example in just plain java how to parse a pem file. If you have an encrypted private key it will get a bit more verbose, see here for more: Parsing encrypted PKCS#8 encoded pem file programatically