Android okhttp3.0配置https的自簽證書和信任所有證書

1.Https相關(guān)知識

1.1 http與https的區(qū)別

HTTP協(xié)議傳輸?shù)臄?shù)據(jù)都是未加密的,也就是明文的,因此使用HTTP協(xié)議傳輸隱私信息非常不安全,為了保證這些隱私數(shù)據(jù)能加密傳輸,于是網(wǎng)景公司設(shè)計了SSL(Secure Sockets Layer)協(xié)議用于對HTTP協(xié)議傳輸?shù)臄?shù)據(jù)進(jìn)行加密,從而就誕生了HTTPS。簡單來說,HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,要比http協(xié)議安全。

HTTPS和HTTP的區(qū)別主要如下:

  • https協(xié)議需要到ca申請證書,一般免費(fèi)證書較少,因而需要一定費(fèi)用。
  • http是超文本傳輸協(xié)議,信息是明文傳輸,https則是具有安全性的ssl加密傳輸協(xié)議。
  • http和https使用的是完全不同的連接方式,用的端口也不一樣,前者是80,后者是443。
  • http的連接很簡單,是無狀態(tài)的;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全。

1.2 Https的優(yōu)點(diǎn)

  • 認(rèn)證用戶和服務(wù)器,確保數(shù)據(jù)發(fā)送到正確的客戶機(jī)和服務(wù)器;(驗(yàn)證證書)
  • 加密數(shù)據(jù)以防止數(shù)據(jù)中途被竊??;(加密)
  • 維護(hù)數(shù)據(jù)的完整性,確保數(shù)據(jù)在傳輸過程中不被改變。(摘要算法)

2.Okhttp中使用自簽名證書

一般支持https的網(wǎng)站,都是CA(Certificate Authority)機(jī)構(gòu)頒發(fā)的證書,但是一般該機(jī)構(gòu)頒發(fā)的證書需要提供費(fèi)用且有使用時間的限制,到期需要續(xù)費(fèi)。否則默認(rèn)該鏈接是不信任的,通過okHttp無法直接訪問。

但是我們可以使用自簽的方式,通過JDK自帶的keytool.exe 生成一個自己的證書,然后使用該證書內(nèi)容。雖然也是會出現(xiàn)提示“不安全”,但是我們可以通過okhttp訪問鏈接。

2.1 使用自簽證書

將證書文件放置在assets目錄(也可以放置在其他目錄下,只要能正確讀取到該文件),在創(chuàng)建OkhttpClient對象時sslSocketFactory()將該證書信息添加。

private SSLContext getSLLContext() {
        SSLContext sslContext = null;
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            InputStream certificate = mContext.getAssets().open("gdroot-g2.crt");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            String certificateAlias = Integer.toString(0);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
            sslContext = SSLContext.getInstance("TLS");
            final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslContext;
    }

通過以上代碼可以看出,通過InputStream方式讀取證書信息,因此為了避免將證書文件打包到APK中,我們可以直接將證書文件內(nèi)容放置在String中,將該字符串轉(zhuǎn)為流的形式。

在使用okhttp時,將其設(shè)置到sslSocketFactory中。

OkHttpClient httpClient = new OkHttpClient().newBuilder()
                .sslSocketFactory(getSLLContext().getSocketFactory())
                .build();

2.2 信任所有證書

通過添加證書的形式,可以實(shí)現(xiàn)客戶端訪問Https服務(wù)端的功能,但是如果服務(wù)端更換證書內(nèi)容,那么客戶端需要相應(yīng)的更換https證書,否則無法正常交互獲取不到數(shù)據(jù),我們可以通過自定義X509TrustManager的形式實(shí)現(xiàn)來規(guī)避所有的證書檢測,實(shí)現(xiàn)信任所有證書的目的。

 private OkHttpClient getHttpsClient() {
        OkHttpClient.Builder okhttpClient = new OkHttpClient().newBuilder();
        //信任所有服務(wù)器地址
        okhttpClient.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                //設(shè)置為true
                return true;
            }
        });
        //創(chuàng)建管理器
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] x509Certificates,
                    String s) throws java.security.cert.CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] x509Certificates,
                    String s) throws java.security.cert.CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }
        } };
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            //為OkHttpClient設(shè)置sslSocketFactory
            okhttpClient.sslSocketFactory(sslContext.getSocketFactory());

        } catch (Exception e) {
            e.printStackTrace();
        }

        return okhttpClient.build();
    }

創(chuàng)建X509TrustManager對象,并實(shí)現(xiàn)其中的方法,由于X509TrustManager是通用證書格式,只需要拿到該格式就行。最后init該安全協(xié)議,將其放入okhttp的sslSocketFactory中。
由于Retrofit只是對Okhttp網(wǎng)絡(luò)接口的封裝,因此實(shí)際使用中,該方法同樣適用于Retrofit中。

歡迎關(guān)注曉涵說(CSDN)、xukang868(github)賬號信息,查看更多文章。

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

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

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