HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

最近在调用一些https的接口,然后采用的认证方式是用户名+密码。

这个时候调用接口则会提示httpclient未认证的错误,导致接口无法调用:

HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated。

出现此问题主要是在请求过程中证书的问题,程序使用的客户端并未安装服务器要求的证书,所以会产生此问题。

下面是我找到的解决方法。

方法一: httpClient jar包版本为4.1.x

    public static HttpClient getHttpClient(HttpClient base) {
        try {
            SSLContext ctx = SSLContext.getInstance("SSL");
            X509TrustManager tm = new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
            };

            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager mgr = base.getConnectionManager();
            SchemeRegistry registry = mgr.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
            return new DefaultHttpClient(mgr, base.getParams());
        } catch (Exception e) {
            logger.warn("{}", e);
            return null;
        }
    }

调用的方法如下:

HttpClient httpClient = ToolUtil.getHttpClient(new DefaultHttpClient());

此时问题已经完美解决了。

然而在之后的使用过程中,我发现4.1版本的httpClient jar包里面没有httpPatch,但最新的4.5版本是有的。于是果断用最新的4.5.3版本的httpClient包。

用了这个jar包之后满屏幕的删除线,很多代码都被@Deprecated注解掉了。改!

解决HttpClient javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated这个问题的代码当然也是要随着一起改的了,于是乎我找到了方法二。

方法二: httpClient jar包为4.5.x版本。

    public static CloseableHttpClient getHttpClient() {
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }}, new SecureRandom());
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
            CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().setSSLSocketFactory(socketFactory).build();
            return closeableHttpClient;
        } catch (Exception e) {
            logger.warn("create closeable http client failed!");
            return HttpClientBuilder.create().build();
        }
    }
调用示例:

httpClient = ToolUtil.getHttpClient();

在这个里面我遇到的最大问题是SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER 竟然也被@Deprecated注释了。然后终于找到了一个替代方案:用NoopHostnameVerifier.INSTANCE替换之。这个是在 http://stackoverflow.com/questions/23201648/httpclient-4-3-x-fixing-deprecated-code-to-use-current-httpclient-implementatio 最下面一个答案中找到的。


最后附上完整的java代码,主要是给出import头文件。

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ToolUtil {
    private static final Logger logger = LoggerFactory.getLogger(ToolUtil.class);

    public static HttpClient getHttpClient(HttpClient base) {
        try {
            SSLContext ctx = SSLContext.getInstance("SSL");
            X509TrustManager tm = new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
            };

            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager mgr = base.getConnectionManager();
            SchemeRegistry registry = mgr.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
            return new DefaultHttpClient(mgr, base.getParams());
        } catch (Exception e) {
            logger.warn("{}", e);
            return null;
        }
    }


    public static CloseableHttpClient getHttpClient() {
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }}, new SecureRandom());
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
            CloseableHttpClient closeableHttpClient = HttpClientBuilder.create().setSSLSocketFactory(socketFactory).build();
            return closeableHttpClient;
        } catch (Exception e) {
            logger.warn("create closeable http client failed!");
            return HttpClientBuilder.create().build();
        }
    }


}

本文参考:

http://stackoverflow.com/questions/24752485/httpclient-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-when

http://stackoverflow.com/questions/23201648/httpclient-4-3-x-fixing-deprecated-code-to-use-current-httpclient-implementatio


猜你喜欢

转载自blog.csdn.net/wanghuiqi2008/article/details/55260073
今日推荐