java忽略證書驗證(相容http,https)進行get/post請求--使用(org.apache.httpcomponents httpclient客戶端)
阿新 • • 發佈:2018-12-18
這兩天的任務就是跟測試接觸,在測試過程傳送資料請求上游資訊時,報了:
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(); } }
下次遇到這問題,希望能以最快的速度解決,是本文章的目的!