javax.net.ssl.SSLPeerUnverifiedException: Host name does not match the certificate subject provided by the peer

81,974

Solution 1

I have spent an hour trying to fix the same issue. This is what I come up with:

final SSLConnectionSocketFactory sslsf;
try {
    sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault(),
            NoopHostnameVerifier.INSTANCE);
} catch (NoSuchAlgorithmException e) {
    throw new RuntimeException(e);
}

final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", new PlainConnectionSocketFactory())
        .register("https", sslsf)
        .build();

final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
cm.setMaxTotal(100);
httpClient = HttpClients.custom()
        .setSSLSocketFactory(sslsf)
        .setConnectionManager(cm)
        .build();

Hopefully, it works and does not use any deprecated code (httpclient 4.4.1).

Solution 2

Replace this

CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
            .setConnectionManager(cm).build();

with

CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .setConnectionManager(cm)
            .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
            .build();

If the certificate isn't signed (not even self-signed), then you can do

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class TrustAllStrategy implements TrustStrategy {
    @Override
    public boolean isTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        return true;
    }
}

Then

builder.loadTrustMaterial(new TrustAllStrategy());

EDIT: this

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext, //for you this is builder.build()
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
);

Solution 3

Thanks to all the solutions. I have been trying all the solutions available online for 1.5 days now and finally it worked now. Here is the working code

 SSLContextBuilder builder = new SSLContextBuilder();
 builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE);
 Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", new PlainConnectionSocketFactory())
            .register("https", sslConnectionSocketFactory)
            .build();

 PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
 cm.setMaxTotal(100);
 CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslConnectionSocketFactory)
            .setConnectionManager(cm)
            .build();
 HttpPost httpPost = new HttpPost(url);
 httpPost.setEntity(postEntity);
 httpPost.expectContinue();
 CloseableHttpResponse response = httpclient.execute(httpPost);

Solution 4

This is what I came up with:

 SSLContextBuilder sslcontext = new SSLContextBuilder();
 sslcontext.loadTrustMaterial(null, new TrustSelfSignedStrategy());
 httpclient = HttpAsyncClients.custom().setSSLContext(sslcontext.build()).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
      .build();

Solution 5

After trying most of the solution suggested on this page and other related stackoverflow discussions, I found AJC's response above works with apache httpclient version 4.5.

Reason: While creating SSLConnectionSocketFactory if the HostVerifier is not specified in the constructor, it does not get set and the DefaultHostVerifier is used. So line 3 of AJC's solutionmakes the difference.

(Atleast this is the behavior in apache httpclient 4.5.3 )

Share:
81,974
Admin
Author by

Admin

Updated on March 18, 2020

Comments

  • Admin
    Admin about 4 years

    I follow many links on stackoverflow and tried many solutions, but none of them worked for me. I'm using WSO2 API manager version 1.9.1. I am facing following error:

    Exception in thread "main" javax.net.ssl.SSLPeerUnverifiedException: Host name 'XXXXXXXXX' does not match the certificate subject provided by the peer (CN=localhost, O=WSO2, L=Mountain View, ST=CA, C=US)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:465)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:395)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:134)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
        at com.java.pushNotifications.WSO2DemoClient.main(WSO2DemoClient.java:49)
    

    I developed the following Java code. Please help me what's going wrong here. I need to connect insecure way and allow connections to SSL sites without certs.

    public static void main(String[] args) throws ClientProtocolException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
    
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", new PlainConnectionSocketFactory())
                    .register("https", sslsf)
                    .build();
    
            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
            cm.setMaxTotal(2000);//max connection
    
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
                    .setConnectionManager(cm).build();
    
            HttpGet httpGet = new HttpGet("https://XXXXXXXXXX:8243/token");
            CloseableHttpResponse response = httpclient.execute(httpGet);
    
            String json =" {\"data\":\"grant_type=password&username=test&password=test123\"}";
    
            try {
                HttpPost httpost = new HttpPost(url);
                httpost.setHeader("Content-Type", "application/x-www-form-urlencoded");
                httpost.setHeader("Authorization", "Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
    
                httpost.setEntity(new StringEntity(json));
    
                HttpResponse httpResponse = httpclient.execute(httpost);
    
                System.out.println(httpResponse.getStatusLine());
            }
            finally {
                response.close();
            }
    
            String responseString1 = new BasicResponseHandler().handleResponse(response);
            System.out.println("Response : "+responseString1);
        }