程序員筆記|當年用httpclient時踩過的那些坑

【技術沙龍002期】數據中臺:宜信敏捷數據中臺建設實踐|宜信技術沙龍 將於5月23日晚8點線上直播,點擊報名html

1、前言

httpclient是java開發中最經常使用的工具之一,一般你們會使用其中比較基礎的api去調用遠程。長期開發爬蟲,會接觸httpclient不經常使用的api,同時會遇到各式各樣的坑,本文將總結這些年遇到的坑及相應的解決方案。java

2、問題及解決方案

問題1:Received fatal alert: handshake_failure算法

問題背景api

開發某省份移動爬蟲時,加載首頁會報標題錯誤,嘗試各類辦法都很差使,後來發現換了jdk1.8就能夠了。通過長達一個星期源碼探尋,發現錯誤源頭是http在握手時,加密算法不支持。安全

jdk1.8如下版本不支持256位(TLS_DHE_RSA_WITH_AES_256_CBC_SHA )網絡

解決方案oracle

一、下載jce擴展包 http://www.oracle.com/technetwork/cn/java/javase/downloads/jce-7-download-432124.htmlapp

二、替換/jre/lib/security/裏面的兩個jardom

三、覆蓋後若是報錯The jurisdiction policy files are not signed by a trusted signer!,說明下載的版本不對,要下對應jdk版本的。socket

問題2:Certificates does not conformto algorithm constraints

問題背景

用mvn打包時報錯, security.cert.CertificateException: Certificates does not conform toalgorithm constraints

緣由是在java1.6以後的這個配置文件中,認爲MD2的加密方式安全性過低,於是不支持這種加密方式,同時也不支持RSA長度小於1024的密文。

須要修改 JAVA_HOME/jre/lib/security/java.security #jdk.certpath.disabledAlgorithms=MD2, RSA keySize < 1024

可是這樣作須要把每臺機器都改一遍,若是新加機器忘記改了,就會繼續報錯。所以須要一套方法,只在代碼層解決問題。

解決方案

經查源碼發現了觸發問題的代碼位置,經過強制繼承SSLContextBuilder,並強制把private的keymanagers和trustmanagers的值置空就能夠解決這個問題了。

代碼以下:

static class MySSLContextBuilder extends SSLContextBuilder {
   static final String TLS   = "TLS";
   static final String SSL   = "SSL";
   private String protocol;
   private Set keymanagers;
   private Set trustmanagers;
   private SecureRandom secureRandom;
   public MySSLContextBuilder() {
      super();
      this.keymanagers = new HashSet();
      this.trustmanagers = new HashSet();
   }
}

問題3:超時時間不生效

問題背景

不少人在使用httpclient時會到網上去找例子,例子中常常會有相似這樣的設置

httpGet.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, !isAutoRelocal);

使用上述方法發送httpclient,在讀取配置時,若是發現getParams不爲空,則會使得之前設置的全部參數都失效,而使用這裏設置的,結果是致使超時時間失效。

解決方案

request.getParams().setParameter是過時方法,其中每一項參數在RequestConfig裏都有對應的,遍歷出來替換一遍便可。

boolean isRedirect = true;
        if(request != null) {
            HttpParams params = request.getParams();
            if (params instanceof HttpParamsNames) {
                // 暫時只支持這個類型
                isRedirect = params.getBooleanParameter(
                        ClientPNames.HANDLE_REDIRECTS, true);
            }
            // 清空request
            request.setParams(new BasicHttpParams());
        }
        if(timeOut > 0) {
            builder = RequestConfig.custom().setConnectionRequestTimeout(timeOut).setConnectTimeout(timeOut).setSocketTimeout(timeOut).setRedirectsEnabled(isRedirect).setCookieSpec(CookieSpecs.BEST_MATCH);
        } else {
            builder = RequestConfig.custom().setConnectionRequestTimeout(connectionTimeout).setConnectTimeout(connectionTimeout).setRedirectsEnabled(isRedirect).setSocketTimeout(socketTimeout).setCookieSpec(CookieSpecs.BEST_MATCH);
        }

問題4:fildder監聽問題

問題背景

開發爬蟲常常會使用fildder來監控網絡請求,可是使用httpclient時想用fildder會很難,網上查各類辦法都很差用。

下面爲你們來排個錯,使用下面方法就能夠完美解決這個問題,讓fildder監控更容易。

解決方案

首先java端

// client builder
HttpClientBuilder builder = HttpClients.custom();
if(useFidder) {
            // 默認fidder寫死
            builder.setProxy(new HttpHost("127.0.0.1", 8888));
}

fildder端

tools->fiddler options->https->actions->export root certificate to ... \bin\keytool.exe -import -file C:\Users\\Desktop\FiddlerRoot.cer -keystore FiddlerKeystore -alias Fiddler

問題5:支持gzip

問題及解決方案

有些網站返回進行了gzip壓縮,返回內容是壓縮的結果,須要解壓。

代碼以下:

HttpClient wrappedHttpClient =  builder.setUserAgent(requestUA)
                .addInterceptorLast(new HttpResponseInterceptor() {
                    @Override
                    public void process(HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
                        HttpEntity httpEntity = httpResponse.getEntity();
                        Header header = httpEntity.getContentEncoding();
                        if (header != null) {
                            for (HeaderElement element : header.getElements()) {
                                if ("gzip".equalsIgnoreCase(element.getName())) {
                                    httpResponse.setEntity(new GzipDecompressingEntity(httpResponse.getEntity()));
                                }
                            }
                        }
                    }
                })

做者:劉鵬飛

來源:宜信技術學院

相關文章
相關標籤/搜索