并不是所有的https请求都需要按照下面的代码进行设置,如果遇到下面的问题,则需要这么做。
javax.net.ssl.SSLException: hostname in certificate didn't match:
采用绕过验证的方式处理https请求
需要指定信任所有证书,并指定不校验域名。
DefaultHttpClient
代码:
public static DefaultHttpClient getHttpClient(String url, Proxy proxy)
throws Exception {
SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy() {
// 信任所有
@Override
public boolean isTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
return true;
}
});
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
// 连接池设置
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
schemeRegistry.register(new Scheme("https", 443, sf));
PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);
cm.setMaxTotal(200); // 连接池里的最大连接数
cm.setDefaultMaxPerRoute(20); // 每个路由的默认最大连接数
// 其它设置
DefaultHttpClient httpClient = new DefaultHttpClient(cm);
CookieStore cookieStore = httpClient.getCookieStore();
// 添加语言cookie
BasicClientCookie2 langCookie = new BasicClientCookie2("LangKey", "cs");
langCookie.setVersion(0);
langCookie.setDomain(Utility.getPurceHost(url));
langCookie.setPath("/");
cookieStore.addCookie(langCookie);
HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
public boolean retryRequest(IOException exception,
int executionCount, HttpContext context) {
if (executionCount >= 3) {
// 如果超过最大重试次数,那么就不要继续了
return false;
}
if (exception instanceof NoHttpResponseException) {
// 如果服务器丢掉了连接,那么就重试
return true;
}
if (exception instanceof SSLHandshakeException) {
// 不要重试SSL握手异常
return false;
}
HttpRequest request = (HttpRequest) context
.getAttribute(ExecutionContext.HTTP_REQUEST);
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent) {
// 如果请求被认为是幂等的,那么就重试
return true;
}
return false;
}
};
httpClient.setHttpRequestRetryHandler(myRetryHandler);
// 设置读取超时时间
httpClient.getParams().setIntParameter("http.socket.timeout",
SnatchConstant.TIMEOUT);
// 设置连接超时超时
httpClient.getParams()
.setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT,
SnatchConstant.TIMEOUT);
// 添加代理
if (null != proxy) {
if (proxy.getUsed() == 1) {
String ip = proxy.getIp();// 代理ip
int port = proxy.getPort();// 代理端口
String proxyUserName = proxy.getUsername();// 代理账号用户名
String proxyPassword = proxy.getPassword();// 代理账号密码
if (!(Utility.isNull(ip) || port <= 0)) {
// 访问的目标站点,端口和协议
httpClient.getCredentialsProvider().setCredentials(
new AuthScope(ip, port),
new UsernamePasswordCredentials(proxyUserName,
proxyPassword));
// 代理的设置
HttpHost proxyHost = new HttpHost(ip, port);
httpClient.getParams().setParameter(
ConnRoutePNames.DEFAULT_PROXY, proxyHost);
}
}
}
return httpClient;
}
CloseableHttpClient
如果是CloseableHttpClient,可以使用下面的代码:
public static CloseableHttpClient createSSLClientDefault(String url, Proxy proxy){
try {
CookieStore cookieStore = new BasicCookieStore();
// 添加语言cookie
BasicClientCookie2 langCookie = new BasicClientCookie2("LangKey", "cs");
langCookie.setVersion(0);
langCookie.setDomain(Utility.getPurceHost(url));
langCookie.setPath("/");
cookieStore.addCookie(langCookie);
RequestConfig config = null;
if (config == null) {
config = RequestConfig.custom().setConnectTimeout(SnatchConstant.TIMEOUT).setSocketTimeout(SnatchConstant.TIMEOUT).build();
}
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
//信任所有
@Override
public boolean isTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
return HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultCookieStore(cookieStore).setDefaultRequestConfig(config).setRetryHandler((new HttpRequestRetryHandler() {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount >= 3) {
// 如果超过最大重试次数,那么就不要继续了
return false;
}
if (exception instanceof NoHttpResponseException) {
// 如果服务器丢掉了连接,那么就重试
return true;
}
if (exception instanceof SSLHandshakeException) {
// 不要重试SSL握手异常
return false;
}
HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent) {
// 如果请求被认为是幂等的,那么就重试
return true;
}
return false;
}
})).build();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return HttpClients.createDefault();
}
参考:轻松把玩HttpClient之配置ssl,采用绕过证书验证实现https
加载证书来访问HTTPS网站
DefaultHttpClient
DefaultHttpClient hc = new DefaultHttpClient();
//加载证书
java.security.KeyStore trustStore = java.security.KeyStore.getInstance(java.security.KeyStore.getDefaultType());
//"123456"为制作证书时的密码
trustStore.load(new FileInputStream(new File("你的证书位置")), "123456".toCharArray());
org.apache.http.conn.ssl.SSLSocketFactory socketFactory = new org.apache.http.conn.ssl.SSLSocketFactory(trustStore);
//不校验域名
socketFactory.setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//这个8446是和被访问端约定的端口,一般为443
org.apache.http.conn.scheme.Scheme sch = new org.apache.http.conn.scheme.Scheme("https", socketFactory, 8446);
hc.getConnectionManager().getSchemeRegistry().register(sch);
参考:http://blog.csdn.net/wangshfa/article/details/9059089
CloseableHttpClient
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
//加载证书文件
FileInputStream instream = new FileInputStream(new File("/home/victor/my.store"));
try {
trustStore.load(instream, "mypassword".toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(trustStore).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();