这两天的任务就是跟测试接触,在测试过程发送数据请求上游信息时,报了:
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 managerSSLContext 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 paramsMap, boolean isHttps, int timeout) throws IllegalArgumentException, IOException {
if (isHttps) {
System.setProperty("jsse.enableSNIExtension", "false");
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
Iterator iterator = paramsMap.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
Object value = https://www.it610.com/article/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 socketFactoryRegistry = RegistryBuilder.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 managerSSLContext 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();
}
}
【java忽略证书验证(兼容http,https)进行get/post请求--使用(org.apache.httpcomponents httpclient客户端)】下次遇到这问题,希望能以最快的速度解决,是本文章的目的!