Android使用OkHttp訪問自簽名證書的Https接口

轉(zhuǎn)載請注明出處:http://www.itdecent.cn/p/37a73df2146a
本文出自Shawpoo的簡書
我的博客:CSDN博客

前言

在Android開發(fā)中,Okhttp想必大家都不陌生,一個(gè)處理網(wǎng)絡(luò)請求的開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架。

本人在開發(fā)過程中也用了很長一段時(shí)間了,但是基本請求的都是http接口。即使訪問https網(wǎng)站也都是綠色的,有個(gè)很特殊的大型購票網(wǎng)站則不是,所以本文主要介紹如何使用Okhttp訪問自簽名證書的https接口。而且公司自己服務(wù)接口也全部換成了https接口,在去年就說ios要強(qiáng)制更換https接口,不然appstore無法上架,最近好像也沒信了,估計(jì)是政策放寬了吧。不管怎樣,今天就拿這個(gè)大型購票網(wǎng)站舉例來說,使用Okhttp訪問購票網(wǎng)站。

獲取簽名證書

購票網(wǎng)站的簽名證書可以在官網(wǎng)上直接下載,或者點(diǎn)擊這里下載即可。srca.cer即為購票網(wǎng)站的簽名證書。

為了方便將簽名證書添加到OkHttp中,可以將簽名證書放在本地的assets文件夾下,為了便于管理我放在了assets/cers目錄下,在代碼中可以通過流的形式獲取到證書文件。

添加證書一般是在訪問接口之前添加,為了方便,我放在了Application中,這樣的話,在應(yīng)用啟動(dòng)的時(shí)候就會(huì)已經(jīng)將添加添加到了OkHttp中。

使用Okhttp訪問接口

  • 使用Android Studio的話,直接添加Okhttp的依賴:
compile 'com.squareup.okhttp3:okhttp:3.3.1'

  • 獲取簽名證書文件流
//獲取證書流
private void readHttpsCer() {
        try {
            InputStream is = getAssets().open("cers/srca.cer");
            NetConfig.addCertificate(is); // 這里將證書讀取出來,,放在配置中byte[]里
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
  • NetConfig相關(guān)代碼:
// 證書數(shù)據(jù)
    private static List<byte[]> CERTIFICATES_DATA = new ArrayList<>();

    /**
     * 添加https證書
     *
     * @param inputStream
     */
    public synchronized static void addCertificate(InputStream inputStream) {
        Log.i(TAG, "#addCertificate inputStream = " + inputStream);
        if (inputStream != null) {

            try {
                int ava = 0;// 數(shù)據(jù)當(dāng)次可讀長度
                int len = 0;// 數(shù)據(jù)總長度
                ArrayList<byte[]> data = new ArrayList<>();
                while ((ava = inputStream.available()) > 0) {
                    byte[] buffer = new byte[ava];
                    inputStream.read(buffer);
                    data.add(buffer);
                    len += ava;
                }

                byte[] buff = new byte[len];
                int dstPos = 0;
                for (byte[] bytes : data) {
                    int length = bytes.length;
                    System.arraycopy(bytes, 0, buff, dstPos, length);
                    dstPos += length;
                }

                CERTIFICATES_DATA.add(buff);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * https證書
     *
     * @return
     */
    public static List<byte[]> getCertificatesData() {
        return CERTIFICATES_DATA;
    }

  • 編寫工具類,將證書添加到OkHttp中:
 public static OkHttpClient createOkHttp() {

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        // 添加證書
        List<InputStream> certificates = new ArrayList<>();
        List<byte[]> certs_data = NetConfig.getCertificatesData();

        // 將字節(jié)數(shù)組轉(zhuǎn)為數(shù)組輸入流
        if (certs_data != null && !certs_data.isEmpty()) {
            for (byte[] bytes : certs_data) {
                certificates.add(new ByteArrayInputStream(bytes));
            }
        }


        SSLSocketFactory sslSocketFactory = getSocketFactory(certificates);
        if (sslSocketFactory != null) {
            builder.sslSocketFactory(sslSocketFactory);
        }

        return builder.build();
    }


    /**
     * 添加證書
     *
     * @param certificates
     */
    private static SSLSocketFactory getSocketFactory(List<InputStream> certificates) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            try {
                for (int i = 0, size = certificates.size(); i < size; ) {
                    InputStream certificate = certificates.get(i);
                    String certificateAlias = Integer.toString(i++);
                    keyStore.setCertificateEntry(certificateAlias, certificateFactory
                            .generateCertificate(certificate));
                    if (certificate != null)
                        certificate.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManagerFactory trustManagerFactory =
                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

  • 查看測試使用結(jié)果:

將自簽名證書添加到Okhttp中,通過創(chuàng)建的OkHttpClient對(duì)象,我們就可以訪問相關(guān)的Https接口服務(wù)了。

點(diǎn)擊下載Demo

參考閱讀

Okhttp官網(wǎng)
Okhttp on Github

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

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

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