Retrofit 2.0 詳解(二)加載https請求(轉(zhuǎn))

前面已經(jīng)講了 Retrofit 2.0 詳解(一)基本用法齿椅,下面講一下怎么用Retrofit2.0加載https請求昌犹。后面提到的Retrofit都是指Retrofit2.0。

科普一下,什么是HTTPS域仇?

簡單來說放椰, **HTTPS **就是 “安全版”HTTP , **HTTPS = HTTP + SSL **作烟。HTTPS相當于在應用層和TCP層之間加入了一個SSL(或TLS),SSL層對從應用層收到的數(shù)據(jù)進行加密砾医。 **TLS/SSL中使用了RSA非對稱加密拿撩,對稱加密以及HASH算法 **。

RSA算法基于一個十分簡單的數(shù)論事實:將兩個大素數(shù)相乘十分容易如蚜,但那時想要對其乘積進行因式分解卻極其困難压恒,因此可以將乘積公開作為加密密鑰。

SSL:(Secure Socket Layer错邦,安全套接字層)探赫,為Netscape所研發(fā),用以保障在Internet上數(shù)據(jù)傳輸之安全撬呢,利用數(shù)據(jù)加密(Encryption)技術伦吠,可確保數(shù)據(jù)在網(wǎng)絡上之傳輸過程中不會被截取。它已被廣泛地用于Web瀏覽器與服務器之間的身份認證和加密數(shù)據(jù)傳輸魂拦。SSL協(xié)議位于TCP/IP協(xié)議與各種應用層協(xié)議之間毛仪,為數(shù)據(jù)通訊提供安全支持。

SSL協(xié)議可分為兩層:

SSL記錄協(xié)議(SSL Record Protocol):它建立在可靠的傳輸協(xié)議(如TCP)之上芯勘,為高層協(xié)議提供數(shù)據(jù)封裝潭千、壓縮、加密等基本功能的支持借尿。
SSL握手協(xié)議(SSL Handshake Protocol):它建立在SSL記錄協(xié)議之上刨晴,用于在實際的數(shù)據(jù)傳輸開始前,通訊雙方進行身份認證路翻、協(xié)商加密算法狈癞、交換加密密鑰等。

TLS:(Transport Layer Security茂契,傳輸層安全協(xié)議)蝶桶,用于兩個應用程序之間提供保密性和數(shù)據(jù)完整性。TLS 1.0是IETF(Internet Engineering Task Force掉冶,Internet工程任務組)制定的一種新的協(xié)議真竖,它建立在SSL 3.0協(xié)議規(guī)范之上脐雪,是SSL 3.0的后續(xù)版本,可以理解為SSL 3.1恢共,它是寫入了 RFC的战秋。

該協(xié)議由兩層組成: TLS 記錄協(xié)議(TLS Record)和 TLS 握手協(xié)議(TLS Handshake)。


http://www.reibang.com/p/64172ccfb73b

進入正文

由于Retrofit是基于OkHttp實現(xiàn)的讨韭,因此想通過Retrofit實現(xiàn)HTTPS需要給Retrofit設置一個OkHttp代理對象用于處理HTTPS的握手過程脂信。代理代碼如下:

OkHttpClient okHttpClient = new OkHttpClient.Builder()
    .sslSocketFactory(SSLHelper.getSSLCertifcation(context))//為OkHttp對象設置SocketFactory用于雙向認證
    .hostnameVerifier(new UnSafeHostnameVerifier())
    .build();
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://10.10.8.88:8443")
    .addConverterFactory(GsonConverterFactory.create())//添加 json 轉(zhuǎn)換器
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//添加 RxJava 適配器
    .client(okHttpClient)//添加OkHttp代理對象
    .build();

證書制作:

首先對于雙向證書驗證,也就是說透硝,
客戶端持有服務端的公鑰證書狰闪,并持有自己的私鑰, 服務端持有客戶的公鑰證書濒生,并持有自己私鑰埋泵,建立連接的時候,客戶端利用服務端的公鑰證書來驗證服務器是否上是目標服務器罪治;服務端利用客戶端的公鑰來驗證客戶端是否是目標客戶端秋泄。( 請參考RSA非對稱加密以及HASH校驗算法

服務端給客戶端發(fā)送數(shù)據(jù)時,需要將服務端的證書發(fā)給客戶端驗證规阀,驗證通過才運行發(fā)送數(shù)據(jù)恒序,同樣,客戶端請求服務器數(shù)據(jù)時谁撼,也需要將自己的證書發(fā)給服務端驗證歧胁,通過才允許執(zhí)行請求。

下面我畫了一個圖厉碟,來幫助大家來理解雙向認證的過程喊巍,證書生成流程,以及各個文件的作用箍鼓,大家可以對照具體步驟來看相關格式說明

JKS: 數(shù)字證書庫崭参。 JKS里有KeyEntry和CertEntry,在庫里的每個Entry都是靠別名(alias)來識別的款咖。

P12: 是PKCS12的縮寫何暮。同樣是一個 存儲私鑰的證書庫 ,由 .jks 文件導出的铐殃,用戶在PC平臺安裝海洼, 用于標示用戶的身份

CER: 俗稱數(shù)字證書富腊, 目的就是用于存儲公鑰證書 坏逢,任何人都可以獲取這個文件 。

BKS: 由于Android平臺不識別 .keystore.jks 格式的證書庫文件,因此Android平臺引入一種的證書庫格式是整,BKS肖揣。

有些人可能有疑問,為什么Tomcat只有一個server.keystore文件浮入,而客戶端需要兩個庫文件龙优?

因為有時客戶端可能需要訪問過個服務,而服務器的證書都不相同舵盈,因此客戶端需要制作一個truststore 來存儲受信任的服務器的證書列表。因此為了規(guī)范創(chuàng)建一個 truststore.jks 用于存儲受信任的服務器證書球化,創(chuàng)建一個 client.jks 來存儲客戶端自己的私鑰秽晚。對于只涉及與一個服務端進行雙向認證的應用,將 server.cer 導入到 client.jks 中也可筒愚。

具體步驟如下:

注意:確保電腦已經(jīng)配置了java環(huán)境變量

1.生成客戶端keystore
keytool -genkeypair -alias client -keyalg RSA -validity 3650 -keypass 123456 -storepass 123456 -keystore client.jks
2.生成服務端keystore
keytool -genkeypair -alias server -keyalg RSA -validity 3650 -keypass 123456 -storepass 123456 -keystore server.keystore
//注意:CN必須與IP地址匹配赴蝇,否則需要修改host
3.導出客戶端證書
keytool -export -alias client -file client.cer -keystore client.jks -storepass 123456
4.導出服務端證書
keytool -export -alias server -file server.cer -keystore server.keystore -storepass 123456
5.重點:證書交換

將客戶端證書導入服務端keystore中,再將服務端證書導入客戶端keystore中巢掺, 一個keystore可以導入多個證書句伶,生成證書列表。
生成客戶端信任證書庫(由服務端證書生成的證書庫):

keytool -import -v -alias server -file server.cer -keystore truststore.jks -storepass 123456 

將客戶端證書導入到服務器證書庫(使得服務器信任客戶端證書):

keytool -import -v -alias client -file client.cer -keystore server.keystore -storepass 123456
6.生成Android識別的BKS庫文件

用Portecle工具轉(zhuǎn)成bks格式陆淀,最新版本是1.10考余。
下載鏈接:https://sourceforge.net/projects/portecle/
運行protecle.jar將client.jks和truststore.jks分別轉(zhuǎn)換成client.bks和truststore.bks,然后放到android客戶端的assert目錄下

File -> open Keystore File -> 選擇證書庫文件 -> 輸入密碼 -> Tools -> change keystore type -> BKS -> save keystore as -> 保存即可

這個操作很簡單,如果不懂可自行百度轧苫。

我在Windows下生成BKS的時候會報錯失敗楚堤,后來我換到CentOS用OpenJDK1.7立馬成功了,如果在這步失敗的同學可以換到Linux或Mac下操作含懊,
將生成的BKS拷貝回Windows即可身冬。

7.配置Tomcat服務器

找到Tomcat安裝目錄 conf\server.xml文件,配置8443端口

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           clientAuth="true" sslProtocol="TLS"
           keystoreFile="${catalina.base}/key/server.keystore" keystorePass="123456"
           truststoreFile="${catalina.base}/key/server.keystore" truststorePass="123456"/>

備注: - keystoreFile:指定服務器密鑰庫岔乔,可以配置成絕對路徑酥筝,本例中是在Tomcat目錄中創(chuàng)建了一個名為key的文件夾,僅供參考雏门。
- keystorePass:密鑰庫生成時的密碼
- truststoreFile:受信任密鑰庫嘿歌,和密鑰庫相同即可
- truststorePass:受信任密鑰庫密碼

8.Android App編寫B(tài)KS讀取創(chuàng)建證書自定義的SSLSocketFactory
private final static String CLIENT_PRI_KEY = "client.bks";
private final static String TRUSTSTORE_PUB_KEY = "truststore.bks";
private final static String CLIENT_BKS_PASSWORD = "123456";
private final static String TRUSTSTORE_BKS_PASSWORD = "123456";
private final static String KEYSTORE_TYPE = "BKS";
private final static String PROTOCOL_TYPE = "TLS";
private final static String CERTIFICATE_FORMAT = "X509";
    
public static SSLSocketFactory getSSLCertifcation(Context context) {
  SSLSocketFactory sslSocketFactory = null;
  try {
    // 服務器端需要驗證的客戶端證書,其實就是客戶端的keystore
    KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);// 客戶端信任的服務器端證書
    KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE);//讀取證書
    InputStream ksIn = context.getAssets().open(CLIENT_PRI_KEY);
    InputStream tsIn = context.getAssets().open(TRUSTSTORE_PUB_KEY);//加載證書
    keyStore.load(ksIn, CLIENT_BKS_PASSWORD.toCharArray());
    trustStore.load(tsIn, TRUSTSTORE_BKS_PASSWORD.toCharArray());
    ksIn.close();
    tsIn.close();
    //初始化SSLContext
    SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE);
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(CERTIFICATE_FORMAT);
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CERTIFICATE_FORMAT);
    trustManagerFactory.init(trustStore);
    keyManagerFactory.init(keyStore, CLIENT_BKS_PASSWORD.toCharArray());
    sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); 
    
    sslSocketFactory = sslContext.getSocketFactory();
    
  } catch (KeyStoreException e) {...}//省略各種異常處理茁影,請自行添加
  return sslSocketFactory;
}
9.Android App獲取SSLFactory實例進行網(wǎng)絡訪問

結(jié)束語

由于雙向認證涉及的原理知識太多搅幅,有些地方我也是一筆帶過,本文想著重介紹證書的制作以及應用呼胚。在此奉勸各位茄唐,如果不了解 RSA非對稱加密,對稱加密以及HASH校驗算法 的同學,最好還是先看書學習一下沪编。

了解原理對于進步來說是十分有幫助的呼盆,網(wǎng)上的資料魚龍混雜,不了解原理的話你根本無從分辨網(wǎng)上文章的正誤蚁廓。

文章轉(zhuǎn)載至 ChongmingLiu访圃,感謝這位兄弟的分享!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末相嵌,一起剝皮案震驚了整個濱河市腿时,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饭宾,老刑警劉巖批糟,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異看铆,居然都是意外死亡徽鼎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門弹惦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來否淤,“玉大人,你說我怎么就攤上這事棠隐∈眨” “怎么了?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵助泽,是天一觀的道長汁雷。 經(jīng)常有香客問我,道長报咳,這世上最難降的妖魔是什么侠讯? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮暑刃,結(jié)果婚禮上厢漩,老公的妹妹穿的比我還像新娘。我一直安慰自己岩臣,他們只是感情好溜嗜,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著架谎,像睡著了一般炸宵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谷扣,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天土全,我揣著相機與錄音捎琐,去河邊找鬼。 笑死裹匙,一個胖子當著我的面吹牛瑞凑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播概页,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼籽御,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惰匙?” 一聲冷哼從身側(cè)響起技掏,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎项鬼,沒想到半個月后哑梳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡秃臣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年涧衙,在試婚紗的時候發(fā)現(xiàn)自己被綠了哪工。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奥此。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖雁比,靈堂內(nèi)的尸體忽然破棺而出稚虎,到底是詐尸還是另有隱情,我是刑警寧澤偎捎,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布蠢终,位于F島的核電站,受9級特大地震影響茴她,放射性物質(zhì)發(fā)生泄漏寻拂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一丈牢、第九天 我趴在偏房一處隱蔽的房頂上張望祭钉。 院中可真熱鬧,春花似錦己沛、人聲如沸慌核。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垮卓。三九已至,卻和暖如春师幕,著一層夾襖步出監(jiān)牢的瞬間粟按,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留钾怔,地道東北人碱呼。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像宗侦,于是被迫代替她去往敵國和親愚臀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

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