標籤:exec 因此 blog err boolean .exe port 3.1 asi
版本說明
httpclinet:4.3.1
jdk:1.6
tomcat:6
異常資訊
Caused by: javax.net.ssl.SSLException: Certificate for <**> doesn‘t contain CN or DNS subjectAlt at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:178) at org.apache.http.conn.ssl.BrowserCompatHostnameVerifier.verify(BrowserCompatHostnameVerifier.java:54) at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:152) at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:133) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:291) at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:262) at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118) at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314) at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:357) at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:218) at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194) at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85) at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108) at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106) ... 18 more
背景
使用httpclient忽略認證發起https請求,代碼如下
package cn.org.pcac.ries.httpService.util;import java.io.IOException;import java.security.KeyManagementException;import java.security.NoSuchAlgorithmException;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.util.ArrayList;import java.util.List;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLException;import javax.net.ssl.SSLSession;import javax.net.ssl.SSLSocket;import javax.net.ssl.TrustManager;import javax.net.ssl.X509TrustManager;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.NameValuePair;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.ssl.X509HostnameVerifier;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;public class HttpsSend { public static void main(String[] args) throws Exception { String url = ""; List<NameValuePair> formparams = new ArrayList<NameValuePair>(); HttpPost httpPost = new HttpPost(url); // 設定客戶逾時 RequestConfig defaultRequestConfig = RequestConfig.custom() .setSocketTimeout(9000).setConnectTimeout(9000) .setConnectionRequestTimeout(9000) .setStaleConnectionCheckEnabled(true).build(); // 設定服務端 RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig) .build(); formparams.add(new BasicNameValuePair("param", "")); httpPost.setConfig(requestConfig); CloseableHttpClient httpclient = null; httpclient = HttpClients.custom() .setDefaultRequestConfig(defaultRequestConfig).build(); SSLContext sslcontext = null; if (url.indexOf("https") == 0) { sslcontext = createIgnoreVerifySSL(); httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig) .setSslcontext(sslcontext).build(); } UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); httpPost.setEntity(uefEntity); HttpResponse response = httpclient.execute(httpPost); HttpEntity entity = response.getEntity(); if (entity != null) { // 獲得返回報文 String respons = EntityUtils.toString(entity, "UTF-8"); EntityUtils.consume(entity); System.out.println(respons); } } public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException { SSLContext sc = SSLContext.getInstance("TLS"); X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted( java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] paramArrayOfX509Certificate, String paramString) throws CertificateException { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }; sc.init(null, new TrustManager[] { trustManager }, null); return sc; } }
錯誤原因
跟蹤源碼,異常資訊如下所示:
訪問網站的認證為自簽認證,缺少CN=等資訊,但是我已經忽略認證校正了為什麼還會出現這個問題呢?
發現初始化CloseableHttpClient時,有如下代碼:
因此修改初始化CloseableHttpClient,將
httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig)
.setSslcontext(sslcontext).build();
改成
httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig)
.setHostnameVerifier(hostnameVerifier)
.setSslcontext(sslcontext).build();
增加變數
public static X509HostnameVerifier hostnameVerifier = new X509HostnameVerifier() {br/>@Override
return true;
}
@Override public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException { } @Override public void verify(String host, X509Certificate cert) throws SSLException { } @Override public void verify(String host, SSLSocket ssl) throws IOException { }};
記錄一下訪問https報doesn‘t contain CN or DNS sub錯誤