2

I've been trying to send RestTemplate requests to an API url that looks as follows:

https://api.something.hostname.net/api/key=key&parameter1=val1&etc

which was supposed to return a JSON response. But it would give the following error: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <api.something.hostname.net> doesn't match any of the subject alternative names: [sni-required.hostname.com]

I would then implement my own RestTemplate as follows (from this link):

public RestTemplate getRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException {


        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();

        requestFactory.setHttpClient(createAcceptSelfSignedCertificateClient());

        RestTemplate restTemplate = new RestTemplate(requestFactory);


        return restTemplate;
    }


    private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
            throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

        // use the TrustSelfSignedStrategy to allow Self Signed Certificates
        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadTrustMaterial(new TrustSelfSignedStrategy())
                .build();

        // we can optionally disable hostname verification.
        // if you don't want to further weaken the security, you don't have to include this.
        HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

        // create an SSL Socket Factory to use the SSLContext with the trust self signed certificate strategy
        // and allow all hosts verifier.
        SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

        // finally create the HttpClient using HttpClient factory methods and assign the ssl socket factory
        return HttpClients
                .custom()
                .setSSLSocketFactory(connectionFactory)
                .build();
    }

And now it throws:

Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching api.rasp.yandex.net found.
    at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:214) ~[na:1.8.0_172]
    at sun.security.util.HostnameChecker.match(HostnameChecker.java:96) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200) ~[na:1.8.0_172]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) ~[na:1.8.0_172]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596) ~[na:1.8.0_172]
    ... 56 common frames omitted

The link example makes a successful request using HttpClient. Can I solve the issue for RestTemplate or do I have to move onto HttpClient?

How do I disable SSL checks for the time being in the development stage? Is this a problem that can be solved locally or is it the certificate issue of the API provider?

  • The solution can be found in this answer. https://stackoverflow.com/a/34841989 – chao_chang Oct 02 '18 at 08:19
  • Thanks @charles_chung, I'll take a look at it a bit later. But for the time being I've found a solution. The problem was somehow related to Spring Boot. Making a single restTemplate request to the required URL at the start of the application strangely solves the issue – Daulet Amirkhanov Oct 02 '18 at 09:57

0 Answers0