1. 程式人生 > >peer not authenticated的終極解決方案

peer not authenticated的終極解決方案

一、前述

  使用httpclient發起https請求時,可能會遇到如下異常:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:397)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128)
    at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:
399) at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:143)

  網上搜索也能找到一大堆的解決方案,但大部分都類似,就是跳過證書的驗證,於是跟著稀裡糊塗的將程式碼拷貝下來使用,結果呢?有的能解決,有的依舊報這個錯誤。到底咋回事呢,接下來就說說這個問題的解決方案。

二、緣由

  首先,要知道導致報這個異常的原因不僅僅是因為證書校驗不通過。

  都知道,在我們通過https連結伺服器時,伺服器會給我們返回一個證書,這個證書可能經過CA認證,也可能是未認證的自制證書,客戶端拿到這個證書後會對這個證書進行驗證,如果是經過CA驗證的證書,自然證書校驗就能通過,自制證書自然就校驗不同過,從而導致上邊的異常。

  證書校驗通過後,還需要校驗訪問的域名是否和證書指定的域名是否匹配。未匹配也會導致如上異常。

  上邊兩步都校驗通過了才開始進行握手,但握手也有可能失敗,從而導致上邊的異常。

  以上三個步驟中任何一個出了問題,都會連線失敗。

三、解決方法

  通過網上搜索我們大部分都會找到類似如下的解決方案:

SSLContext sslContext;
    try {
        sslContext = SSLContext.getInstance("SSL");
        // set up a TrustManager that trusts everything
try { sslContext.init(null, new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( X509Certificate[] certs, String authType) { } public void checkServerTrusted( X509Certificate[] certs, String authType) { } } }, new SecureRandom()); } catch (KeyManagementException e) { } SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

  這個解決方案針對以上的三個步驟中的第一步,就是放棄對證書的校驗,但是第二部還可能有問題,要想徹底解決還需要跳過對域名的校驗。這裡給出最終的解決方案:

try {
                SSLContext sslContext = SSLContext.getInstance("TLS");
                X509TrustManager tm = new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                };
                sslContext.init(null,new TrustManager[]{tm},null);
                sslSocketFactory = new SSLSocketFactory(sslContext,new X509HostnameVerifier(){
                    @Override
                    public boolean verify(String s, SSLSession sslSession) {
                        return true;
                    }

                    @Override
                    public void verify(String host, SSLSocket ssl) throws IOException {

                    }

                    @Override
                    public void verify(String host, X509Certificate cert) throws SSLException {

                    }

                    @Override
                    public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {

                    }
                });
            } catch (GeneralSecurityException e) {
                log.error("create SSLSocketFactory error:{}",e);
            }
            return sslSocketFactory;

  這裡不僅放棄對證書的校驗,也放棄對hostname的校驗,通過空實現X509HostnameVerifier類。

  以上這個解決方案就會徹底解決問題嗎?不一定,還有一個步驟就是握手的步驟也可能出問題,怎麼判斷是不是握手步驟出了問題呢?可以在程式碼裡做如下設定:

System.setProperty("javax.net.debug","ssl");

  做了以上設定後,就可以列印https建立連線的日誌了,如下:

true
addingastrustedcert:
證書內容略去
triggerseedingofSecureRandom
doneseedingSecureRandom
executingrequestGETHTTP/1.1
Ignoringunavailableciphersuite:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ignoringunavailableciphersuite:TLS_DHE_RSA_WITH_AES_256_CBC_SHA
Ignoringunavailableciphersuite:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoringunsupportedciphersuite:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoringunsupportedciphersuite:TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoringunavailableciphersuite:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoringunavailableciphersuite:TLS_DHE_DSS_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoringunsupportedciphersuite:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoringunsupportedciphersuite:TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoringunavailableciphersuite:TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
Ignoringunavailableciphersuite:TLS_RSA_WITH_AES_256_CBC_SHA
Ignoringunsupportedciphersuite:TLS_RSA_WITH_AES_128_CBC_SHA256
Allowunsaferenegotiation:false
Allowlegacyhellomessages:true
Isinitialhandshake:true
Issecurerenegotiation:false
%%Nocachedclientsession
***ClientHello,TLSv1
……
main,WRITE:TLSv1Handshake,length=181
main,READ:TLSv1Alert,length=2
main,RECVTLSv1ALERT:fatal,handshake_failure
main,calledcloseSocket()
main,handlingexception:javax.net.ssl.SSLHandshakeException:Receivedfatalalert:handshake_failure

  通過最後一個片語“handshake_failure”,你一定可以確定是握手失敗了。這一般是因為客戶端的加密機制太簡單,伺服器認為不安全,握手失敗。

  握手失敗解決方案就比較簡單,下載一個UnlimitedJCEPolicyJDK7.zip 。在http://www.oracle.com/technetwork/java/javase/downloads/index.html下載就好了。裡面包含了兩個jar。在你的/lib/security,替換後,重新執行看看。

  如果以上這些還沒能解決,那我也是不知道了,可以留言,我跟你一塊找答案^_^。

相關推薦

org.hibernate.MappingNotFoundException: resource:**.hbm.xml not found終極解決方案

終於把問題找到了: 凡是出現這個錯誤,一定是路徑的問題。所以 1,檢查你的路徑寫對了沒有,對映檔案的路徑,配置檔案的路徑 2,如果還是出現錯誤,那一定是寫的方式不對~ 如圖 這是我的配置~一開始,我總是直接複製,全路徑,如圖 我一開始總是複製全路徑,然後往裡面放~所以,總出現找不到路

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated 問題解決

最近線下除錯銀聯支付時報錯: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SS

httpclient 出現peer not authenticated 問題解決 https

轉自:http://jingfeng198.blog.163.com/blog/static/46255920129153312606/ 用下面的程式碼就可以搞定。例子程式碼使用httpclient4.1 import java.security.cert.X509Cer

peer not authenticated終極解決方案

一、前述   使用httpclient發起https請求時,可能會遇到如下異常: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated at sun.security.ssl.SSLSessionImpl.getPe

peer not authenticated和Could not generate DH keypair解決方法

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated 網上基本上都是信任所有證書來解決 SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER這個方法的程式碼如下:

關於spring boot整合mybatis使用oracle資料庫出現could not load:oracle.jdbc.driver.OracleDriver問題的終極解決方案

  由於開發用到資料庫為oracle,特地從外網下載下來與spring整合的mybatis的jar包,接下來本以為輕鬆愉快的加入oracle驅動的pom依賴即可,結果報錯,經查詢發現Maven倉庫由於版權的原因沒有oracle的驅動jar包。   當時考慮的是

Android新版本開發工具的Android SDK Manager只有4.3及出現SSLPeerUnverified peer not authenticated解決辦法

新下載的Android新版本開發工具的Android SDK Manager只有4.3,如圖: 在網上找到一個解決辦法:在c:\windows\system32\drivers\etc\hosts檔案開啟,在檔案的最下面加上 74.125.237.1 dl-ssl.goo

解決在gradle構建project時,發生peer not authenticated錯誤的方法

開發十年,就只剩下這套架構體系了! >>>   

Android studio 報錯 gradel project sync failed Error:Cause: peer not authenticated

authent post -m -h cal all del erro 文件 在網上找了半天,應該是找不到gradel的路徑,試了網上非常多方法。本人解決例如以下: 在android studio中設置gradle。打開File-> settings->Gr

Plugin with id 'com.novoda.bintray-release' not found.的解決方案

添加 pan mage nbsp file eas 分享 pat img import Module的時候,有時候會提示Plugin with id ‘com.novoda.bintray-release‘ not found. 點擊Open File,定位到該Mod

https 調用驗證失敗 peer not authenticated

實現 不同 not org 失敗 下載 efault ltr net https 調用驗證失敗 peer not authenticated 報錯日誌: Caused by: javax.net.ssl.SSLPeerUnverifiedException: pe

Unity 使用C/C++ 跨平臺終極解決方案(PC,iOS,Android,以及支持C/C++的平臺)

細節 -h comment 個人 tle lan source 多說 sharp https://blog.csdn.net/fg5823820/article/details/47865741 PC的其實根本不用說,畢竟C#和C++交互的文章已經夠多了,當然我自認為經過幾

(通用)Android App代碼混淆終極解決方案【轉】

rar $$ enable 知識 object ava write android ref App雖然沒有那麽的高大上,但是代碼的混淆是代表了程序員對App的責任心, 也是對App安全的一點點保證。今天我會將自己做Android混淆的過程和體會分享給大家,也避免大家少走彎路

connection reset by peer問題總結及解決方案

net 方維 catch 火墻 tst buffer 整理 pos 在服務器 找遍了 中英文網站,翻遍了能找的角落,發現了出現故障的原因和原理,及改如何處理,這裏記錄下,希望能幫助到有需要的小夥伴,少走點彎路, 以上就整理內容: connection res

IDEA 文檔註釋 亂碼 終極... 解決方案

RM nbsp odin src exe enc 最後一行 span png idea bin 目錄 下 phpstorm64.exe.vmoptions 最後一行添加 : -Dfile.encoding=UTF-8 IDEA 文檔註釋 亂

新手搭建 WordPress 網站終極解決方案 基於 Bitnami 堆棧快速搭建完美個人博客(Blog)

分享 成了 rdp 網上 特色 雲服務 nco BE tro 為了搭建一個自己的博客,對於沒有相關知識的我來說,真的時相當不容易,經過很長時間的摸索研究,總算是搭起了這個博客(Blog),那麽第一篇文章就是來記錄一下,經過反復的折騰後感覺最適合我自己的一個方法,文章包含很多

Could NOT find OpenSSL解決方案

version 0.9.8 ram 方案 3.2 PE most open fin Call Stack (most recent call first): CMakeLists.txt:122 (find_package)CMake Error at C:/Progra

雲原生:雲計算時代命題之終極解決方案

圖片 hit 讀者 最優 趨勢 打包成 容器化 公有雲 sca 雲原生:雲計算時代命題之終極解決方案 https://blog.csdn.net/broadview2006/article/details/80131068 2017年08月17日 14:35:05

eclipse儲存jsp頁面的時候出現save could not be completed解決方案

Eclipse中新建一個jsp頁面檔案預設的字元編碼是ISO-8859-1: 如果頁面有中文的話,儲存的時候會出現下面的錯誤: 這時只需要把上面的三個iso-8859-1換成utf-8即可。 問題解決,可是下一次遇到這個問題又得重新換一次,麻煩,所以下面介紹一個一勞永逸的

PHP 實現大資料(30w量級)表格匯出(匯出excel) 提高效率,減少記憶體消耗,終極解決方案

使用php做專案開發的同學,一定都會有過使用php進行excel表格匯出的經歷,當匯出少量資料還好,一旦資料量級達到5w、 10w、20w甚至30以上的時候就會面臨同樣的問題: 1、匯出時間變得很慢,少則1分鐘,多則好幾分鐘,資料量一旦上來,還可能面臨導不出來的困窘(這種匯出效率正常人都會受