HttpClient進行https請求
阿新 • • 發佈:2019-02-16
並不是所有的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();
}
載入證書來訪問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);
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();