对等方未在 java 中进行身份验证

Peer not authenticated in java

与此异常相关的几乎所有post我都去了。实际上我的问题是我有一个 java 应用程序,通过它我正在点击 URL 并从它那里得到响应。

命中 URL 的代码是:

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

这里我得到 javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

因此,经过一些 Google 搜索后,我知道我可以在应用程序 运行 的 java 密钥库中导入证书。所以我在密钥库中导入了证书,这段代码正在运行。但我不想要这个解决方案,所以经过更多搜索后,我知道我可以使用 TrustManager 来做同样的事情,而无需将证书导入密钥库。所以我写了这样的代码:

@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;
    }

此代码也有效,但我的问题是我没有检查与证书相关的任何内容以及连接的可信度。调试后我知道只有 checkServerTrusted 命中。所以我在 checkServerTrusted 中写了一些东西来验证 certs 中的证书和我的应用程序中的证书,比如一些 .cer 或 .crt 文件。

我们将不胜感激。

在@EpicPandaForce 之后更新(使用 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();
        }

从技术上讲,鉴于您使用的是 Apache HttpClient 4.x,更简单的解决方案如下:

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

其中trustStore是这样初始化的

    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;
}

然后创建HttpClient

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

编辑:我的确切代码是这样的:

        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();