1. 程式人生 > >java忽略證書驗證(相容http,https)進行get/post請求--使用(org.apache.httpcomponents httpclient客戶端)

java忽略證書驗證(相容http,https)進行get/post請求--使用(org.apache.httpcomponents httpclient客戶端)

這兩天的任務就是跟測試接觸,在測試過程傳送資料請求上游資訊時,報了:

javax.net.ssl.SSLException: hostname in certificate didn't match

截圖:
在這裡插入圖片描述
含義就是說現在程式執行的域名,與請求的證書不一致,不匹配導致的。那麼解決方案必定是把證書忽略了,也就是不驗證證書的情況下請求上游資訊了。
在解決這個問題的過程中。領導給過我一個demo,可惜這個demo是org.apache.httpcomponents 4.5版本的,而專案中用到的是org.apache.httpcomponents 4.3.6的,兩者有一些區別 經過仔細看底層程式碼,最後發現,其實是否忽視證書的驗證,關鍵還是要看這個截圖的第一行:
在這裡插入圖片描述


也就是底層的實現,需要用到Abstractactverifier.verify這個類的這個方法,原始碼如下:

    @Override
    public final boolean verify(final String host, final SSLSession session) {
        try {
            final Certificate[] certs = session.getPeerCertificates();
            final X509Certificate x509 = (X509Certificate) certs[0];
            verify(host, x509);
            return true;
        } catch(final SSLException ex) {
            if (log.isDebugEnabled()) {
                log.debug(ex.getMessage(), ex);
            }
            return false;
        }
    }

關鍵點不讓他去驗證即可。
解決方法如下:
(看方法註釋即可,註釋有忽略驗證的,就可以把這方法拷貝使用)

package util;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;

/**
 * Http 客戶端請求
 *
 * @author leaflyhuang
 */
@Component("cn.webank.pmbank.cftac.common.util.HttpClientUtil")
public class HttpClientUtil {

    private final static Logger LOG = LoggerFactory.getLogger(HttpClientUtil.class);


	//提交資訊-可以POST資料
    public static Object submit(String url, boolean isHttps, HttpMethod httpMethod, EntityType entityType,
                                byte[] bytes) throws SocketException {
        if (isHttps) {
            System.setProperty("jsse.enableSNIExtension", "false");
        }
      
        HttpURLConnection conn = null;
        try {
            // Create a trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }};

            // Install the all-trusting trust manager

            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            URL conUrl = new URL(url);
            conn = (HttpURLConnection) conUrl.openConnection();
            conn.setReadTimeout(35000);
            conn.setConnectTimeout(35000);
            if (httpMethod == HttpMethod.POST || bytes != null) {
                conn.setDoOutput(true);
            }
            conn.setDoInput(true);
            conn.connect();
            if (bytes != null) {
                DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream());
                outputStream.write(bytes);
                outputStream.flush();
                outputStream.close();
            }

            // if (conn.getResponseCode() >= 200 && conn.getResponseCode() <
            // 300) {
            InputStream inputStream = conn.getInputStream();
            if (inputStream != null) {
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int length = 0;
                while ((length = inputStream.read(buffer)) != -1) {
                    stream.write(buffer, 0, length);
                }
                inputStream.close();
                if (entityType == EntityType.STRING) {
                    return stream.toString();
                }
                return stream.toByteArray();

            }
            // } else {
            // throw new Exception(url + " server return "
            // + conn.getResponseCode() + " status");
            // }
        } catch (SocketException | SocketTimeoutException socketException) {
           
            throw new SocketException("SocketException: " + socketException.getMessage());
        } catch (Exception e) {

        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
        return null;
    }


    private CloseableHttpClient closeableHttpClient = null;
    @Value("${proxy.ip:}")
    private String proxyIp;
    @Value("${proxy.port:0}")
    private int proxyPort;

//get 請求
    public String getEntity(String url, boolean isHttps, int timeout) throws IllegalArgumentException, IOException {
        if (isHttps) {
            System.setProperty("jsse.enableSNIExtension", "false");
        }

        if (closeableHttpClient == null) {
//            closeableHttpClient = createHttpClientWithProxy();
            closeableHttpClient = createNoVerifyClient();
        }
        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
        httpGet.setConfig(requestConfig);
        try (CloseableHttpResponse response = closeableHttpClient.execute(httpGet)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                return null;
            }
            HttpEntity entity = response.getEntity();
            byte[] byteArray = EntityUtils.toByteArray(entity);
            String ret = new String(byteArray);
            return ret;
        } catch (Exception e) {
         
            return null;
        }

    }


	//post請求
    public Object postEntity(String url, Map<String, Object> paramsMap, boolean isHttps, int timeout) throws IllegalArgumentException, IOException {
        if (isHttps) {
            System.setProperty("jsse.enableSNIExtension", "false");
        }
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        Iterator<String> iterator = paramsMap.keySet().iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            Object value = paramsMap.get(key);
            if (value instanceof File) {
                FileBody fileBody = new FileBody((File) value);
                builder.addPart(key, fileBody);
            } else if (value instanceof byte[]) {
                byte[] byteVlue = (byte[]) value;
                ByteArrayBody byteArrayBody = new ByteArrayBody(byteVlue, key);
                builder.addPart(key, byteArrayBody);
            } else {
                throw new IllegalArgumentException("未知資料型別!目前僅支援file型別與byte型別");
            }
        }
        closeableHttpClient = createNoVerifyClient();
        HttpPost httpPost = new HttpPost(url);

        HttpEntity build = builder.build();
        httpPost.setEntity(build);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
        httpPost.setConfig(requestConfig);
        try (CloseableHttpResponse response = closeableHttpClient.execute(httpPost)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                return null;
            }
            HttpEntity entity = response.getEntity();
            byte[] byteArray = EntityUtils.toByteArray(entity);
            String ret = new String(byteArray);
            return (Object) ret;
        }

    }


	
	//沒有忽略證書建立 CloseableHttpClient
    private CloseableHttpClient createHttpClientWithProxy() {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        //代理
        if (StringUtils.isNotBlank(proxyIp)) {
            HttpHost proxy = new HttpHost(proxyIp, proxyPort, "http");
            httpClientBuilder.setProxy(proxy);
        }
        httpClientBuilder.setMaxConnTotal(200);
        httpClientBuilder.setMaxConnPerRoute(100);
        closeableHttpClient = httpClientBuilder.build();
        return closeableHttpClient;
    }

	
	
	
    /**
     * 忽視所有證書驗證-使用org.apache.httpcomponents 4.5版本
     */
    public static CloseableHttpClient acceptsUntrustedCertsHttpClient(String proxyHost, int proxyPort)
            throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

        // setup a Trust Strategy that allows all certificates.
        SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
            public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                return true;
            }
        }).build();

        httpClientBuilder.setSslcontext(sslContext);

        // don't check Hostnames, either.
        // use SSLConnectionSocketFactory.getDefaultHostnameVerifier(), if you don't want to weaken
//        final X509HostnameVerifier hostnameVerifier = getX509HostnameVerifier();
        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;//org.apache.httpcomponents 4.3.6版本沒有的
        // here's the special part:
        // -- need to create an SSL Socket Factory, to use our weakened "trust strategy";
        // -- and create a Registry, to register it.
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, null);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", sslSocketFactory).build();
        // now, we create connection-manager using our Registry. allows multi-threaded use
        PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connMgr.setMaxTotal(200);
        connMgr.setDefaultMaxPerRoute(100);
        httpClientBuilder.setConnectionManager(connMgr);

        HttpHost httpHost = new HttpHost(proxyHost, proxyPort);
        httpClientBuilder.setProxy(httpHost);

        // finally, build the HttpClient;
        CloseableHttpClient client = httpClientBuilder.build();
        return client;
    }



    /**
     * 忽視所有證書驗證使用org.apache.httpcomponents 4.3.6版本
     */
    public CloseableHttpClient createNoVerifyClient() {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }};

            // Install the all-trusting trust manager

            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new SecureRandom());
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sc);
            HttpClientBuilder httpClientBuilder = HttpClients.custom().setSSLSocketFactory(sslsf);
            //代理
            if (StringUtils.isNotBlank(proxyIp)) {
                HttpHost proxy = new HttpHost(proxyIp, proxyPort);
                httpClientBuilder.setProxy(proxy);
            }
            httpClientBuilder.setMaxConnTotal(200);
            httpClientBuilder.setMaxConnPerRoute(100);
            closeableHttpClient = httpClientBuilder.build();
            return closeableHttpClient;
        } catch (KeyManagementException e) {
          
        } catch (NoSuchAlgorithmException e) {
           
        }
        return HttpClients.createDefault();
    }
}

下次遇到這問題,希望能以最快的速度解決,是本文章的目的!