简体   繁体   中英

Peer not authenticated in java

I have gone to almost all the post related to this exception. Actually my problem is I have an java application through which I am hitting an URL and getting response from it.

code to hit URL is :

HttpGet getRequest = new HttpGet("https://urlto.esb.com");
HttpResponse httpResponse = null;       
DefaultHttpClient httpClient = new DefaultHttpClient();
httpResponse = httpClient.execute(getRequest); 

Here I am getting javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

So after some Google search I come to know that I can import certificate in keystore of java where the application is running. so I imported certificate in keystore and this code is working. but i don't want this solution so after some more searching I come to know that I can use TrustManager for the same thing without importing certificate into keystore. So I have written code like:

@Test
    public void withTrustManeger() throws Exception {
        DefaultHttpClient httpclient = buildhttpClient();
        HttpGet httpGet = new HttpGet("https://urlto.esb.com");
        HttpResponse response = httpclient.execute( httpGet );

        HttpEntity httpEntity = response.getEntity();
        InputStream inputStream = httpEntity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                inputStream));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        inputStream.close();
        String jsonText = sb.toString();
        System.out.println(jsonText);
    }

    private DefaultHttpClient buildhttpClient() throws Exception {
        DefaultHttpClient httpclient = new DefaultHttpClient();

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, getTrustingManager(), new java.security.SecureRandom());

        SSLSocketFactory socketFactory = new SSLSocketFactory(sc);
        Scheme sch = new Scheme("https", 443, socketFactory);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);
        return httpclient;
    }

    private TrustManager[] getTrustingManager() {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // Do nothing               
            }

            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // Do nothing
            }

        } };
        return trustAllCerts;
    }

This code is also working but My question is I am not checking anything related to certificates then how connection is trusted. after debugging I come to know that only checkServerTrusted is hitting. So I have write something in checkServerTrusted to validate certificates that come in certs and the one which is in my application like some .cer or .crt file.

Every Help will be appreciated.

Update after @EpicPandaForce (Using Apache HttpClient 4.3)

        try 
        {
            keyStore = KeyStore.getInstance("JKS");
            InputStream inputStream = new FileInputStream("E:\\Desktop\\esbcert\\keystore.jks");
            keyStore.load(inputStream, "key".toCharArray());
            SSLContextBuilder sslContextBuilder = SSLContexts.custom().loadTrustMaterial(keyStore, new TrustSelfSignedStrategy());
            sslcontext = sslContextBuilder.build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext);
            HttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            HttpGet httpGet = new HttpGet("https://url.esb.com");
            HttpResponse response = httpclient.execute( httpGet );

            HttpEntity httpEntity = response.getEntity();
            InputStream httpStram = httpEntity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    httpStram));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            httpStram.close();
            inputStream.close();
            String jsonText = sb.toString();
            System.out.println(jsonText);

        } 
        catch(Exception e) 
        {
            System.out.println("Loading keystore failed.");
            e.printStackTrace();
        }

Technically, seeing as you are using Apache HttpClient 4.x, a simpler solution would be the following:

    SSLContext sslcontext = null;
    try {
        SSLContextBuilder sslContextBuilder = SSLContexts.custom()
            .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy());
        sslcontext = sslContextBuilder.build();

Where trustStore is initialized like this

    KeyStore keyStore = null;
    try {
        keyStore = KeyStore.getInstance("BKS", BouncyCastleProvider.PROVIDER_NAME); //you can use JKS if that is what you have
        InputStream inputStream = new File("pathtoyourkeystore");
        try {
            keyStore.load(inputStream, "password".toCharArray());
        } finally {
            inputStream.close();
        }
    } catch(Exception e) {
        System.out.println("Loading keystore failed.");
        e.printStackTrace();
    }
    return keyStore;
}

And then create the HttpClient

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext);
httpclient = HttpClients
                .custom()
                .setSSLSocketFactory(sslsf).build();

EDIT: Exact code for me was this:

        SSLContextBuilder sslContextBuilder = SSLContexts.custom()
            .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy());
        sslcontext = sslContextBuilder.build();

        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext, new String[] {"TLSv1"}, null,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
        );
        httpclient = HttpClients
            .custom()
            .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
            .setSSLSocketFactory(sslsf).build();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM