OkHttp加載https的配置

https簡介

現(xiàn)在網(wǎng)絡(luò)安全越來越受到重視,https作為更加安全的通信協(xié)議應(yīng)用也越來越廣泛。https相對與http有以下優(yōu)勢:

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

對于一個(gè)android開發(fā)來說,目前的網(wǎng)絡(luò)請求框架大部分都是使用okhttp進(jìn)行網(wǎng)絡(luò)請求的,okhttputils,或者retrofit, 所以了解okhttp是如何加載https請求的對于我們平時(shí)開發(fā)有很大的幫助。

訪問自簽名的網(wǎng)站

首先我們將.cer證書文件放到assets文件夾下,其實(shí)你可以隨便放哪,反正能讀取到就行。
然后在我們的OkHttpClientManager里面添加如下的方法:

public void setCertificates(InputStream... certificates) {
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        int index = 0;
        for (InputStream certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));

            try {
                if (certificate != null)
                    certificate.close();
            } catch (IOException e) {
            }
        }

        SSLContext sslContext = SSLContext.getInstance("TLS");

        TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        trustManagerFactory.init(keyStore);
        sslContext.init
                (
                        null,
                        trustManagerFactory.getTrustManagers(),
                        new SecureRandom()
                );
        //.setSslSocketFactory(sslContext.getSocketFactory());


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

}

為了代碼可讀性,我把異常捕獲的部分簡化了,可以看到我們提供了一個(gè)方法傳入InputStream流,InputStream就對應(yīng)于我們證書的輸入流。

代碼內(nèi)部,我們:

  • 構(gòu)造CertificateFactory對象,通過它的generateCertificate(is)方法得到Certificate。
  • 然后講得到的Certificate放入到keyStore中。
  • 接下來利用keyStore去初始化我們的TrustManagerFactory
  • trustManagerFactory.getTrustManagers獲得TrustManager[]初始化我們的SSLContext
  • 最后,設(shè)置我們mOkHttpClient.setSslSocketFactory即可。

這樣就完成了我們代碼的編寫,其實(shí)挺短的,當(dāng)客戶端進(jìn)行SSL連接時(shí),就可以根據(jù)我們設(shè)置的證書去決定是否新人服務(wù)端的證書。

記得在Application中進(jìn)行初始化:

public class MyApplication extends Application
{
 @Override
  public void onCreate()
  {
    super.onCreate();

    try
    {
        OkHttpClientManager.getInstance()
                .setCertificates(getAssets().open("srca.cer"));
    } catch (IOException e)
    {
        e.printStackTrace();
    }

  }

然后我們就可以嘗試訪問自簽名的htpps服務(wù)器接口了。

使用字符串替代證書

下面繼續(xù),有些人可能覺得把證書copy到assets下還是覺得不舒服,其實(shí)我們還可以將證書中的內(nèi)容提取出來,寫成字符串常量,這樣就不需要證書根據(jù)著app去打包了。

圖片.png

使用keytool命令,以rfc樣式輸出。keytool命令是JDK里面自帶的。

有了這個(gè)字符串以后,我們就不需要srca.cer這個(gè)文件了,直接編寫以下代碼:

public class MyApplication extends Application
{
private String CER_12306 = "-----BEGIN CERTIFICATE-----\n" +
        "MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ04xKTAn\n" +
        "BgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMB4X\n" +
        "DTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFowRzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNp\n" +
        "bm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3\n" +
        "DQEBAQUAA4GNADCBiQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb2\n" +
        "9bSotqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/XgY5iFqv6\n" +
        "D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFHle\n" +
        "tne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDov\n" +
        "LzE5Mi4xNjguOS4xNDkvY3JsMS5jcmwwCwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Pt\n" +
        "x1GITGOFLABDWDANBgkqhkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV\n" +
        "23XQ96HU8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQenvQ\n" +
        "og555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A==\n" +
        "-----END CERTIFICATE-----";

@Override
public void onCreate()
{
    super.onCreate();

    OkHttpClientManager.getInstance()
            .setCertificates(new Buffer()
                    .writeUtf8(CER_12306)
                    .inputStream());
}

注意Buffer是okio包下的,okhttp依賴okio。

ok,這樣就省去將cer文件一起打包進(jìn)入apk了。

參考
?著作權(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)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,366評論 25 708
  • 服務(wù)器https配置 配置https操作說明文檔 1、查看服務(wù)器環(huán)境配置(tomcat和apache合并使用) 2...
    南京楊小兵閱讀 9,255評論 0 9
  • 因?yàn)樽罱黫os需要用到https,所以公司的項(xiàng)目都從http的請求轉(zhuǎn)成了https的雙向認(rèn)證,這里我關(guān)于安卓端ht...
    黃海佳閱讀 6,120評論 1 21
  • 夜幕降臨,華燈初上。我獨(dú)自一人騎著電動(dòng)車在這毫無歸屬感城市之中游蕩著。我感覺自己就像一個(gè)皮球。時(shí)不時(shí)的需要給自己充...
    再聚品酒飲茶閱讀 219評論 0 0
  • 上了班之后越來越覺得能將工作與生活平衡好,著實(shí)是一件考驗(yàn)智商和情商的學(xué)問。 如果早上起得早一點(diǎn),我才能有充分的時(shí)間...
    Phei閱讀 3,577評論 37 11

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