Retrofit 2.0 + Okhttp 用HTTPS請求

先說明一下酬蹋,我的是讀取本地資源目錄的證書及老,不是繞過驗(yàn)證抽莱,也不是校驗(yàn)服務(wù)端證書。

這是一個(gè)很簡單的功能骄恶,確實(shí)食铐。 但是沒搞定之前還是難受得丫批。 百度上僧鲁,簡書上的方法都搜過了虐呻,用過了,沒有用寞秃。最后發(fā)現(xiàn)是自己不會(huì)用(我就知道是這樣子的斟叼!mmp) 寫一篇文章記錄一下。希望能夠幫到(估計(jì)也沒有人和我一樣弱雞了)春寿。


正題開始

1.因?yàn)槲覀兊腍5朗涩,經(jīng)常被插入小廣告,于是就提議要搞HTTPS绑改,然后申請去了幾萬谢床,證書下來了(運(yùn)維老哥給到我們手里)

image

然后我看了網(wǎng)上的帖子后綴不一樣,我又屁顛屁顛的跑去問了一下厘线。 老哥給我解釋了一下crt的全稱识腿,然后知道了有人叫crt,有人叫cer造壮。然后我把證書復(fù)制到assets目錄

image

2.然后我開始了雙屏CV操作渡讼,發(fā)現(xiàn)復(fù)制過來不能用。然后我朋友建議我去看看OkGo的項(xiàng)目耳璧。

OkGo

下載下來看了一下硝全,廖大神有寫各種HTTPS的請求方式。真的很全了楞抡! 我用的是方法三伟众。

image

3.然后我直接就是把他的這個(gè)HttpsUtils方法復(fù)制出來了,然后在我自己的請求封裝那里加上召廷。

代碼如下:

image

Tips:之前有些帖子的證書是放在RAW文件夾里凳厢。然后這個(gè)地方腦殘了一下,沒注意getAssets這個(gè)方法竞慢。

然后到這里就結(jié)束了先紫。。筹煮。遮精。吧? 我都打開網(wǎng)易云放歌了! 然后這個(gè)時(shí)候APP跑上來本冲,請求出錯(cuò)准脂。。等等檬洞。狸膏。

看看Logcat這個(gè)東西吧! 請求的地址還是http添怔。

這時(shí)候想到了點(diǎn)什么湾戳,加證書并不會(huì)自動(dòng)給你加S,然后去請求的广料。

乖乖的把請求地址加上S砾脑。~

放歌吧!

放歌請點(diǎn)擊:Time

最后:廖大神的那個(gè)“優(yōu)踢而絲”我放上來吧~


**/****

* ================================================

* 作    者:jeasonlzy(廖子堯)Github地址:https://github.com/jeasonlzy

* 版    本:1.0

* 創(chuàng)建日期:16/9/11

* 描    述:Https相關(guān)的工具類

* 修訂歷史:

* ================================================

*/

public class HttpsUtils {

public static class SSLParams {

public SSLSocketFactorysSLSocketFactory;

        public X509TrustManagertrustManager;

    }

public static SSLParamsgetSslSocketFactory() {

return getSslSocketFactoryBase(null, null, null);

    }

/**

* https單向認(rèn)證

* 可以額外配置信任服務(wù)端的證書策略艾杏,否則默認(rèn)是按CA證書去驗(yàn)證的拦止,若不是CA可信任的證書,則無法通過驗(yàn)證

*/

    public static SSLParamsgetSslSocketFactory(X509TrustManager trustManager) {

return getSslSocketFactoryBase(trustManager, null, null);

    }

/**

* https單向認(rèn)證

* 用含有服務(wù)端公鑰的證書校驗(yàn)服務(wù)端證書

*/

    public static SSLParamsgetSslSocketFactory(InputStream... certificates) {

return getSslSocketFactoryBase(null, null, null, certificates);

    }

/**

* https雙向認(rèn)證

* bksFile 和 password -> 客戶端使用bks證書校驗(yàn)服務(wù)端證書

* certificates -> 用含有服務(wù)端公鑰的證書校驗(yàn)服務(wù)端證書

*/

    public static SSLParamsgetSslSocketFactory(InputStream bksFile, String password, InputStream... certificates) {

return getSslSocketFactoryBase(null, bksFile, password, certificates);

    }

/**

* https雙向認(rèn)證

* bksFile 和 password -> 客戶端使用bks證書校驗(yàn)服務(wù)端證書

* X509TrustManager -> 如果需要自己校驗(yàn)糜颠,那么可以自己實(shí)現(xiàn)相關(guān)校驗(yàn)汹族,如果不需要自己校驗(yàn),那么傳null即可

*/

    public static SSLParamsgetSslSocketFactory(InputStream bksFile, String password, X509TrustManager trustManager) {

return getSslSocketFactoryBase(trustManager, bksFile, password);

    }

private static SSLParamsgetSslSocketFactoryBase(X509TrustManager trustManager, InputStream bksFile, String password, InputStream... certificates) {

SSLParams sslParams =new SSLParams();

        try {

KeyManager[] keyManagers =prepareKeyManager(bksFile, password);

            TrustManager[] trustManagers =prepareTrustManager(certificates);

            X509TrustManager manager;

            if (trustManager !=null) {

//優(yōu)先使用用戶自定義的TrustManager

                manager = trustManager;

            }else if (trustManagers !=null) {

//然后使用默認(rèn)的TrustManager

                manager =chooseTrustManager(trustManagers);

            }else {

//否則使用不安全的TrustManager

                manager =UnSafeTrustManager;

            }

// 創(chuàng)建TLS類型的SSLContext對象其兴, that uses our TrustManager

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

            // 用上面得到的trustManagers初始化SSLContext顶瞒,這樣sslContext就會(huì)信任keyStore中的證書

// 第一個(gè)參數(shù)是授權(quán)的密鑰管理器,用來授權(quán)驗(yàn)證元旬,比如授權(quán)自簽名的證書驗(yàn)證榴徐。第二個(gè)是被授權(quán)的證書管理器,用來驗(yàn)證服務(wù)器端的證書

            sslContext.init(keyManagers, new TrustManager[]{manager}, null);

            // 通過sslContext獲取SSLSocketFactory對象

            sslParams.sSLSocketFactory = sslContext.getSocketFactory();

            sslParams.trustManager = manager;

            return sslParams;

        }catch (NoSuchAlgorithmException e) {

throw new AssertionError(e);

        }catch (KeyManagementException e) {

throw new AssertionError(e);

        }

}

private static KeyManager[]prepareKeyManager(InputStream bksFile, String password) {

try {

if (bksFile ==null || password ==null)return null;

            KeyStore clientKeyStore = KeyStore.getInstance("BKS");

            clientKeyStore.load(bksFile, password.toCharArray());

            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

            kmf.init(clientKeyStore, password.toCharArray());

            return kmf.getKeyManagers();

        }catch (Exception e) {

e.printStackTrace();

        }

return null;

    }

private static TrustManager[]prepareTrustManager(InputStream... certificates) {

if (certificates ==null || certificates.length <=0)return null;

        try {

CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

            // 創(chuàng)建一個(gè)默認(rèn)類型的KeyStore匀归,存儲(chǔ)我們信任的證書

            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

            keyStore.load(null);

            int index =0;

            for (InputStream certStream : certificates) {

String certificateAlias = Integer.toString(index++);

                // 證書工廠根據(jù)證書文件的流生成證書 cert

                Certificate cert = certificateFactory.generateCertificate(certStream);

                // 將 cert 作為可信證書放入到keyStore中

                keyStore.setCertificateEntry(certificateAlias, cert);

                try {

if (certStream !=null) certStream.close();

                }catch (IOException e) {

e.printStackTrace();

                }

}

//我們創(chuàng)建一個(gè)默認(rèn)類型的TrustManagerFactory

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

            //用我們之前的keyStore實(shí)例初始化TrustManagerFactory坑资,這樣tmf就會(huì)信任keyStore中的證書

            tmf.init(keyStore);

            //通過tmf獲取TrustManager數(shù)組,TrustManager也會(huì)信任keyStore中的證書

            return tmf.getTrustManagers();

        }catch (Exception e) {

e.printStackTrace();

        }

return null;

    }

private static X509TrustManagerchooseTrustManager(TrustManager[] trustManagers) {

for (TrustManager trustManager : trustManagers) {

if (trustManagerinstanceof X509TrustManager) {

return (X509TrustManager) trustManager;

            }

}

return null;

    }

/**

* 為了解決客戶端不信任服務(wù)器數(shù)字證書的問題穆端,網(wǎng)絡(luò)上大部分的解決方案都是讓客戶端不對證書做任何檢查袱贮,

* 這是一種有很大安全漏洞的辦法

*/

    public static X509TrustManagerUnSafeTrustManager =new X509TrustManager() {

@Override

        public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {

}

@Override

        public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {

}

@Override

        public X509Certificate[]getAcceptedIssuers() {

return new X509Certificate[]{};

        }

};

    /**

* 此類是用于主機(jī)名驗(yàn)證的基接口。 在握手期間体啰,如果 URL 的主機(jī)名和服務(wù)器的標(biāo)識(shí)主機(jī)名不匹配攒巍,

* 則驗(yàn)證機(jī)制可以回調(diào)此接口的實(shí)現(xiàn)程序來確定是否應(yīng)該允許此連接。策略可以是基于證書的或依賴于其他驗(yàn)證方案荒勇。

* 當(dāng)驗(yàn)證 URL 主機(jī)名使用的默認(rèn)規(guī)則失敗時(shí)使用這些回調(diào)柒莉。如果主機(jī)名是可接受的,則返回 true

*/

    public static HostnameVerifierUnSafeHostnameVerifier =new HostnameVerifier() {

@Override

        public boolean verify(String hostname, SSLSession session) {

return true;

        }

};

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沽翔,一起剝皮案震驚了整個(gè)濱河市兢孝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖跨蟹,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雳殊,死亡現(xiàn)場離奇詭異,居然都是意外死亡喷市,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門威恼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來品姓,“玉大人,你說我怎么就攤上這事箫措「贡福” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵斤蔓,是天一觀的道長植酥。 經(jīng)常有香客問我,道長弦牡,這世上最難降的妖魔是什么友驮? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮驾锰,結(jié)果婚禮上卸留,老公的妹妹穿的比我還像新娘。我一直安慰自己椭豫,他們只是感情好耻瑟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著赏酥,像睡著了一般喳整。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裸扶,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天框都,我揣著相機(jī)與錄音,去河邊找鬼呵晨。 笑死瞬项,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的何荚。 我是一名探鬼主播囱淋,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼餐塘!你這毒婦竟也來了妥衣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎税手,沒想到半個(gè)月后蜂筹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芦倒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年艺挪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兵扬。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡麻裳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出器钟,到底是詐尸還是另有隱情津坑,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布傲霸,位于F島的核電站疆瑰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏昙啄。R本人自食惡果不足惜穆役,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梳凛。 院中可真熱鬧孵睬,春花似錦、人聲如沸伶跷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叭莫。三九已至蹈集,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間雇初,已是汗流浹背拢肆。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留靖诗,地道東北人郭怪。 一個(gè)月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像刊橘,于是被迫代替她去往敵國和親鄙才。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

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