記一次HttpClient+jdk8調用SSLv3接口的問題


1. 環境

org.apache.httpcomponents.httpclient 4.5.10版本 + jdk1.8_202版本

2. 問題

需要用HttpClient調用https接口,該https服務器只支持SSLv3,調用時報錯:Received fatal alert: handshake_failure

3. 解決

百度:鋪天蓋地的告訴我如何讓HttpClient繞過SSL認證,包括類似下面的代碼:赫然出現了SSLv3這樣的關鍵字,然並卵

ocketFactory = new SSLConnectionSocketFactory(
                    contextBuilder.build(),
                    new String[]{"TLSv1.2", "SSLv3", "TLSv1", "TLSv1.1"},
                    null, 
                    NoopHostnameVerifier.INSTANCE
            );

后偶然看到需要更改jdk,因為jdk本身限制了SSLv3協議的使用,也有人說HttpClient根本就不管jdk那一套。遂跑去看源碼:答案是,HttpClient還是符合jdk的設定的。於是解決辦法為:找到你的jre/lib/security下的java.security文件,修改jdk.tls.disabledAlgorithms,把該項配置的SSLv3干掉即可。當然,上面這段代碼還是需要的,詳見org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket方法:關鍵代碼已標紅

if (this.supportedProtocols != null) {
    sslsock.setEnabledProtocols(this.supportedProtocols);
} else {
    allCipherSuites = sslsock.getEnabledProtocols();
    enabledCipherSuites = new ArrayList(allCipherSuites.length);
    arr$ = allCipherSuites;
    len$ = allCipherSuites.length;

    for(i$ = 0; i$ < len$; ++i$) {
        cipherSuite = arr$[i$];
        if (!cipherSuite.startsWith("SSL")) { enabledCipherSuites.add(cipherSuite); }
    }
    if (!enabledCipherSuites.isEmpty()) {
       sslsock.setEnabledProtocols((String[])enabledCipherSuites.toArray(new String[enabledCipherSuites.size()]));
    }
}

 

4. 最后

只怪自己太垃圾。另附:開啟ssl的bug日志:-Djavax.net.debug=ssl,當然也可以-Djavax.net.debug=all,開啟后如果沒有修改jdk配置,你會看到如下輸出:

Ignoring disabled protocol: SSLv3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM