1. 程式人生 > >HttpClient進行https請求

HttpClient進行https請求

並不是所有的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();