X509TrustManager一定能起作用么?

起因

某日部分請(qǐng)求報(bào)"unable to find valid certification path to requested target"姻政,從異常堆棧來(lái)看是代碼里設(shè)置的沒(méi)生效浩考,還是去做證書(shū)校驗(yàn)廊移,證書(shū)校驗(yàn)失敗導(dǎo)致最終拋異常扭粱。


image.png

分析

代碼里確實(shí)在創(chuàng)建sslContext的時(shí)候指定了自定義的X509TrustManager舵鳞,并信任服務(wù)端證書(shū),為啥沒(méi)有生效呢琢蛤?

從下面的代碼看到,在獲取新的httpClient實(shí)例之前抛虏,會(huì)調(diào)用 Protocol.registerProtocol注冊(cè)協(xié)議和sslContext的關(guān)聯(lián)關(guān)系博其。

   public SSLContext createTrustSSLContext(CommunicationConfig config) throws GeneralSecurityException, IOException {
        String protocol = StringUtils.defaultIfBlank(ConfigUtil.getSSLProtocol(config), PROTOCOL);
        SSLContext sslContext = SSLContext.getInstance(protocol);
        TrustManager[] tm = { getForeverTrusterManager() };
        sslContext.init(null, tm, new SecureRandom());
        return sslContext;
    }

 private TrustManager getForeverTrusterManager() {
        return new X509TrustManager() {

            @Override
            public void checkClientTrusted(X509Certificate[] input, String authType) throws CertificateException {
                // 建立這種永遠(yuǎn)信任的連接,不需要校驗(yàn)
            }

            @Override
            public void checkServerTrusted(X509Certificate[] input, String arg1) throws CertificateException {
                // 建立這種永遠(yuǎn)信任的連接迂猴,不需要校驗(yàn)
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[] {};
            }
        };
    }
 private HttpClient getAvailableClient(CommunicationConfig config) {
        try {
            String key = config.getKey();
            HttpClient client = instanceMap.get(key);
            if (client == null) {
                synchronized (instanceMap) {
                    if ((client = instanceMap.get(key)) == null) {
                        // 注冊(cè)https協(xié)議
                        registerSSLProtocol(config);
                        // 創(chuàng)建客戶端
                        client = contructClient(config);
                        // 注冊(cè)協(xié)議處理類(lèi)
                        ClientProtocolHandler handler = ProtocolFactory.getClientProtocolHandler(config.getProtocol()).newInstance();
                        handler.setConfig(config);
                        handlerMap.put(key, handler);
                        instanceMap.put(key, client);
                    }
                }
            }
            return client;
        } catch (Exception e) {
            errorLogger.error("HTTP客戶端注冊(cè)異常{}", e);
            throw new YtgwException(CommunicationErrorCode.NO_CLIENT_FOUND, e);
        }
    }

   private void registerSSLProtocol(CommunicationConfig config) {
        if (config.getProtocol() == TransportProtocol.HTTPS) {
            // 已經(jīng)注冊(cè)過(guò)就不用再注冊(cè)了,如果有自定義協(xié)議用 HTTPS_SCHEMA
            String scheme = ConfigUtil.getHttpsSchema(config);
            TransportURL url = config.getUri();
            SSLContext context = SSLProtocolHelper.create(config);
            SSLSocketFactory socketFactory = context.getSocketFactory();
            ProtocolSocketFactory factory = new SSLSocketFactoryImpl(socketFactory, config);
            // 注冊(cè)的協(xié)議只能使用全小寫(xiě)
            Protocol myHttps = new Protocol(scheme, factory, url.getPort());
            Protocol.registerProtocol(scheme, myHttps);
            logger.info("注冊(cè)HTTPS協(xié)議,scheme={},url={},port={}", scheme, url.getUrl(), url.getPort());
        }
    }

從下面的代碼能看到在打開(kāi)連接的時(shí)候慕淡,會(huì)從protocol對(duì)象獲取socketFactory,這個(gè)socketFactory就是上面注冊(cè)上去的沸毁。


image.png

如果沒(méi)有注冊(cè)對(duì)應(yīng)的協(xié)議峰髓,protocol獲取到的socketFactory又是啥呢?
從下面的代碼能看到protocol會(huì)調(diào)用SSLProtocolSocketFactory.getSocketFactory()創(chuàng)建一個(gè)默認(rèn)的socketFactory息尺,這個(gè)默認(rèn)的socketFactory就是使用最上面異常堆棧里的sun.security.ssl.X509TrustManagerImpl去做證書(shū)的校驗(yàn)携兵,如果證書(shū)有問(wèn)題,就會(huì)出現(xiàn)校驗(yàn)失敗的情況搂誉。

到這里就知道產(chǎn)生問(wèn)題的根本原因了徐紧,如果Protocol.registerProtocol時(shí)注冊(cè)的是協(xié)議A,訪問(wèn)的是協(xié)議B,protocol就會(huì)創(chuàng)建默認(rèn)的socketFactory去做證書(shū)校驗(yàn)并级,最終出現(xiàn)證書(shū)校驗(yàn)失敗的問(wèn)題拂檩。

  public static Protocol getProtocol(String id) 
        throws IllegalStateException {

        if (id == null) {
            throw new IllegalArgumentException("id is null");
        }

        Protocol protocol = (Protocol) PROTOCOLS.get(id);

        if (protocol == null) {
            protocol = lazyRegisterProtocol(id);
        }

        return protocol;
    } 

private static Protocol lazyRegisterProtocol(String id) 
        throws IllegalStateException {

        if ("http".equals(id)) {
            final Protocol http 
                = new Protocol("http", DefaultProtocolSocketFactory.getSocketFactory(), 80);
            Protocol.registerProtocol("http", http);
            return http;
        }

        if ("https".equals(id)) {
            final Protocol https 
                = new Protocol("https", SSLProtocolSocketFactory.getSocketFactory(), 443);
            Protocol.registerProtocol("https", https);
            return https;
        }

        throw new IllegalStateException("unsupported protocol: '" + id + "'");
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嘲碧,隨后出現(xiàn)的幾起案子稻励,更是在濱河造成了極大的恐慌,老刑警劉巖愈涩,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钉迷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡钠署,警方通過(guò)查閱死者的電腦和手機(jī)糠聪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谐鼎,“玉大人舰蟆,你說(shuō)我怎么就攤上這事±旯鳎” “怎么了身害?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)草戈。 經(jīng)常有香客問(wèn)我塌鸯,道長(zhǎng),這世上最難降的妖魔是什么唐片? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任丙猬,我火速辦了婚禮,結(jié)果婚禮上费韭,老公的妹妹穿的比我還像新娘茧球。我一直安慰自己,他們只是感情好星持,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布抢埋。 她就那樣靜靜地躺著,像睡著了一般督暂。 火紅的嫁衣襯著肌膚如雪揪垄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天逻翁,我揣著相機(jī)與錄音饥努,去河邊找鬼。 笑死卢未,一個(gè)胖子當(dāng)著我的面吹牛肪凛,可吹牛的內(nèi)容都是我干的堰汉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼伟墙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼翘鸭!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起戳葵,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤就乓,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后拱烁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體生蚁,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年戏自,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了邦投。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡擅笔,死狀恐怖志衣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猛们,我是刑警寧澤念脯,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站弯淘,受9級(jí)特大地震影響绿店,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜庐橙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一假勿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧怕午,春花似錦废登、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甲锡。三九已至兆蕉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缤沦,已是汗流浹背虎韵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缸废,地道東北人包蓝。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓驶社,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親测萎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子亡电,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 根證書(shū)含義 - 孤舟蓑笠翁,獨(dú)釣寒江雪 - 博客頻道 - CSDN.NET 本文想簡(jiǎn)單談?wù)勀莻€(gè)所謂的...
    拉肚閱讀 2,397評(píng)論 0 1
  • https://blog.csdn.net/lchq1995/article/details/88293047 ...
    洪君_閱讀 668評(píng)論 0 0
  • https://blog.csdn.net/lchq1995/article/details/88293047 ...
    洪君_閱讀 774評(píng)論 0 0
  • 1硅瞧、Https通信介紹 Https 即安全的超文本傳輸協(xié)議份乒,最初是由網(wǎng)景公司創(chuàng)建,Https在Http上面提...
    小豬PICK閱讀 20,918評(píng)論 0 4
  • Https請(qǐng)求 一腕唧、訪問(wèn)HTTPS站點(diǎn) 兩種方法來(lái)模擬發(fā)送HTTP請(qǐng)求或辖,訪問(wèn)HTTP站點(diǎn)。一種方式是通過(guò)java....
    Gothrow閱讀 2,263評(píng)論 0 2