JAVA 不校驗(yàn)HTTPS服務(wù)器證書(shū)

本章是HTTPS那些事兒的第三篇文章,其他相關(guān)文章請(qǐng)參見(jiàn):前言
本篇主要描述JAVA經(jīng)常遇到的場(chǎng)景:不校驗(yàn)服務(wù)器CA證書(shū)。主要包含以下內(nèi)容:

  • HttpsURLConnection不校驗(yàn)服務(wù)器CA證書(shū)
  • Spring RestTemplate不校驗(yàn)服務(wù)器CA證書(shū)

* 注意

本文純手工打造,轉(zhuǎn)載請(qǐng)注明出處。

HttpsURLConnection不校驗(yàn)服務(wù)器CA證書(shū)

有些情況下,雖然服務(wù)器端使用的是https協(xié)議,但是其證書(shū)不是由權(quán)威機(jī)構(gòu)頒發(fā)的,客戶端如果使用jdk默認(rèn)的證書(shū)會(huì)校驗(yàn)失敗。為了在項(xiàng)目初期進(jìn)行調(diào)試,我們可以忽略服務(wù)器證書(shū)校驗(yàn)。由前一篇文章可知,要達(dá)到不校驗(yàn)服務(wù)器證書(shū)的目的,必須將hostname校驗(yàn)和CA證書(shū)校驗(yàn)同時(shí)關(guān)閉。
要忽略hostname校驗(yàn),可以通過(guò)前一篇文章JAVA中HTTPS那些事兒中的HostnameVerifier小節(jié)介紹的case4場(chǎng)景來(lái)實(shí)現(xiàn)。要忽略證書(shū)校驗(yàn),則需要自定義SSLSocketFactory。整體代碼如下:

public void ignore() throws NoSuchAlgorithmException, KeyManagementException {
        // 自定義證書(shū)校驗(yàn)器
        TrustManager[] trustAllCerts = new TrustManager[] {
          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 new X509Certificate[0]; 
            }
          }
        };
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        // 自定義hostname校驗(yàn)器
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    }

從代碼中可以看到setDefaultSSLSocketFactorysetDefaultHostnameVerifier都是HttpsURLConnection的靜態(tài)方法,也就是此處的設(shè)置是全局的。所以在進(jìn)行實(shí)際的HTTPS訪問(wèn)前,調(diào)用一次ignore方法,即可在后續(xù)所有的HTTPS訪問(wèn)中達(dá)到不校驗(yàn)服務(wù)器CA證書(shū)的目的。

Spring RestTemplate不校驗(yàn)服務(wù)器CA證書(shū)

Spring中的RestTemplate是用于訪問(wèn)Restful服務(wù)的便捷工具類,該類依靠更下層的組件來(lái)完成網(wǎng)絡(luò)請(qǐng)求。默認(rèn)使用JDK中的HttpURLConnection,同時(shí)支持配置Apache HttpComponents HttpClient(4.3+)、OkHttp(2.x and 3.x)、Netty4。所以要使RestTemplate在訪問(wèn)HTTPS服務(wù)時(shí)忽略證書(shū)校驗(yàn),其實(shí)需要配置的是底層的實(shí)現(xiàn)組件。

  • 如果使用默認(rèn)實(shí)現(xiàn)HttpURLConnection,如果要忽略證書(shū)只需要按照前一小節(jié)HttpsURLConnection不校驗(yàn)服務(wù)器CA證書(shū)進(jìn)行操作即可。
  • Apache HttpComponents HttpClient(4.3+)不校驗(yàn)CA證書(shū)
    Apache的HttpClient也是依賴于標(biāo)準(zhǔn)的java加密(Java Cryptography-JCE)和安全socket擴(kuò)展(Secure Sockets-JSEE),所以需要忽略證書(shū)同樣需要?jiǎng)?chuàng)建一個(gè)javax.net.ssl.SSLContext。與HttpsURLConnection一樣Apache HttpClient提供可選的HostnameVerifier功能,并提供兩個(gè)實(shí)現(xiàn)類DefaultHostnameVerifier和NoopHostnameVerifier,第一個(gè)采用RFC 2818規(guī)則校驗(yàn)hostname,第二個(gè)則不進(jìn)行校驗(yàn)。如果需要不校驗(yàn)服務(wù)器CA證書(shū),Apache HttpClient提供了一個(gè)幫助了可以直接使用,代碼如下:
public static void main(String[] args) throws IOException, KeyStoreException,
            NoSuchAlgorithmException, KeyManagementException {
        // 配置Apache HttpClient
        HttpClient httpClient = HttpClients
                .custom()
                .setSSLContext(
                        new SSLContextBuilder()
                                .loadTrustMaterial(null, TrustAllStrategy.INSTANCE)
                                .build()
                )
                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                .build();
        // 讓RestTemplate使用Apache HttpClient訪問(wèn)網(wǎng)絡(luò)
        HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        
        RestTemplate restTemplate = new RestTemplate(requestFactory);
        restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
        String resp = restTemplate.getForObject(IgnoreServerCerts.testUrl,
                String.class);
        System.out.println(resp);
    }
  • 其他
    RestTemplate同時(shí)支持使用OkHttp(2.x and 3.x)和Netty4,但是由于項(xiàng)目中暫未所用,我對(duì)這些組件也不熟悉,如果有使用到可以自行研究。

總結(jié)

本篇文章主要介紹的是java中怎么實(shí)現(xiàn)不校驗(yàn)HTTPS服務(wù)器證書(shū),主要介紹JDK中的HttpURLConnection和Apache HttpComponents HttpClient(4.3+)怎么忽略。同時(shí)明確Spring的RestTemplate是依賴于底層網(wǎng)絡(luò)訪問(wèn)組件實(shí)現(xiàn)的Http訪問(wèn),要忽略證書(shū)只需要配置底層組件即可。
至此,本系列文章主要部分已技術(shù),還有最后一篇可供選擇閱讀使用keytool模擬CA證書(shū)頒發(fā)過(guò)程。
本人程序猿一枚,語(yǔ)言能力有限,這個(gè)系列的文章是在工作過(guò)程中積累而來(lái)的,原意僅供自己備忘?,F(xiàn)公開(kāi)出來(lái),也僅是想幫助有需要的人,如有問(wèn)題,可隨時(shí)留言,如果我懂我會(huì)不定期回復(fù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,288評(píng)論 6 342
  • Https請(qǐng)求 一、訪問(wèn)HTTPS站點(diǎn) 兩種方法來(lái)模擬發(fā)送HTTP請(qǐng)求,訪問(wèn)HTTP站點(diǎn)。一種方式是通過(guò)java....
    Gothrow閱讀 2,344評(píng)論 0 2
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,970評(píng)論 1 92
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,695評(píng)論 19 139
  • 一、RestTemplate是什么 環(huán)境約束:spring-web-4.3.9.RELEASE Spring文檔:...
    Trust_FreeDom閱讀 22,349評(píng)論 3 60

友情鏈接更多精彩內(nèi)容