Retrofit Https踩坑記錄

Retrofit Https踩坑記錄

前言

新司機上路仑扑,坑多,本文重點是踩坑菲宴,不詳細講retrofit用法速蕊,本文不推薦使用信任所有證書的做法途乃。

證書

分為多種格式, bks cer jks等,這里使用的是bks格式證書幻枉。

BKS 做法

1.獲取BKS證書碰声,將證書放到項目raw目錄下

準備.cer文件

點擊網(wǎng)站網(wǎng)址欄前的小鎖按鈕,選擇詳細信息熬甫,選擇view certificate胰挑。
顯示證書之后,點擊詳細信息,然后一直下一步洽腺,直到導(dǎo)出.cer文件脚粟。
[圖片上傳失敗...(image-a8333b-1525252236881)]
[圖片上傳失敗...(image-c1a762-1525252236881)]
[圖片上傳失敗...(image-d3e71b-1525252236881)]
[圖片上傳失敗...(image-47173e-1525252236881)]
[圖片上傳失敗...(image-1de838-1525252236881)]
[圖片上傳失敗...(image-812324-1525252236881)]
[圖片上傳失敗...(image-99f797-1525252236881)]

將.cer轉(zhuǎn)換為.bks

在Android應(yīng)用中使用自定義證書,CER轉(zhuǎn)BKS

做法:1覆旱,下載特定版本的JCE Provider包

http://pan.baidu.com/s/1c1ur13y

or

http://www.bouncycastle.org/download/bcprov-jdk15on-146.jar (現(xiàn)在連接失效)

2蘸朋,命令行輸入以下命令

keytool -importcert -v -trustcacerts -alias 位置1 \
-file 位置2 \
-keystore 位置3 -storetype BKS \
-providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
-providerpath 位置4 -storepass 位置5

位置1:是個隨便取的別名
位置2:cer或crt證書的全地址
位置3:生成后bks文件的位置,建議寫全地址
位置4:上面下載JCE Provider包的位置
位置5:生成后證書的密碼。下邊獲取sslsocketfactory中會用到密碼

以下例子:

keytool -importcert -v -trustcacerts -alias xx -file E:\bks\xx.cer -keystore E:\bks\xx.bks -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath E:\bks\bcprov-jdk15on-146.jar -storepass xxxxxx

成功之后會在你指定的位置生成bks文件.然后將文件放到項目raw目錄下扣唱。

2.獲取SSLSocketFactory

這里是https證書認證最關(guān)鍵的代碼藕坯,一定要仔細查看。password和設(shè)置keystore的bks類型一定不要搞錯噪沙。

/**
 * 獲取bks文件的sslsocketfactory
 * @param context
 * @return
 */
public static SSLSocketFactory getSSLSocketFactory(Context context) {
    final String CLIENT_TRUST_PASSWORD = "123456";//信任證書密碼炼彪,該證書默認密碼是123456
    final String CLIENT_AGREEMENT = "TLS";//使用協(xié)議
    final String CLIENT_TRUST_KEYSTORE = "BKS";
    SSLContext sslContext = null;
    try {
        //取得SSL的SSLContext實例
        sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
        //取得TrustManagerFactory的X509密鑰管理器實例
        TrustManagerFactory trustManager = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        //取得BKS密庫實例
        KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
        InputStream is = context.getResources().openRawResource(R.raw.traint);
        try {
            tks.load(is, CLIENT_TRUST_PASSWORD.toCharArray());
        } finally {
            is.close();
        }
        //初始化密鑰管理器
        trustManager.init(tks);
        //初始化SSLContext
        sslContext.init(null, trustManager.getTrustManagers(), null);
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("SslContextFactory", e.getMessage());
    }
    return sslContext.getSocketFactory();
}

3.配置retrofit

String baseUrl = "https://skyish-test.yunext.com";
int[] certificates = {R.raw.traint};
    String[] hostUrls = {baseUrl};
    OkHttpClient client = new okhttp3.OkHttpClient.Builder()
            .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .sslSocketFactory(HTTPSUtils.getSSLSocketFactory(context))
            //.hostnameVerifier(HTTPSUtils.getHostNameVerifier(hostUrls)) 
            .readTimeout(10, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
            .build();

    Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .client(client)
            .build();

配置好retrofit之后就可以使用了。

坑1:SSLContext is not initialized

03-08 15:17:26.804 21672-21672/com.qiwo.enumlistdemo E/AndroidRuntime: FATAL EXCEPTION: main
                                                                       Process: com.qiwo.enumlistdemo, PID: 21672
                                                                       java.lang.RuntimeException: Unable to start activity ComponentInfo{com.qiwo.enumlistdemo/com.qiwo.enumlistdemo.RetrofitHttpsDemoActivity}: java.lang.IllegalStateException: SSLContext is not initialized.
                                                                           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2650)
                                                                           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2720)
                                                                           at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567)
                                                                           at android.os.Handler.dispatchMessage(Handler.java:111)
                                                                           at android.os.Looper.loop(Looper.java:207)
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5917)
                                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
                                                                        Caused by: java.lang.IllegalStateException: SSLContext is not initialized.
                                                                           at com.android.org.conscrypt.OpenSSLContextImpl.engineGetSocketFactory(OpenSSLContextImpl.java:107)
                                                                           at javax.net.ssl.SSLContext.getSocketFactory(SSLContext.java:358)
                                                                           at com.qiwo.api.HTTPSUtils.getSSLSocketFactory(HTTPSUtils.java:158)
                                                                           at com.qiwo.api.DemoHttpsApi.<init>(DemoHttpsApi.java:40)
                                                                           at com.qiwo.enumlistdemo.RetrofitHttpsDemoActivity.initViewAndListener(RetrofitHttpsDemoActivity.java:37)
                                                                           at com.doudou.common.base.BaseSwipeBackAppcompatActivity.onCreate(BaseSwipeBackAppcompatActivity.java:68)
                                                                           at android.app.Activity.performCreate(Activity.java:6307)
                                                                           at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113)
                                                                           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2603)
                                                                           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2720) 
                                                                           at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567) 
                                                                           at android.os.Handler.dispatchMessage(Handler.java:111) 
                                                                           at android.os.Looper.loop(Looper.java:207) 
                                                                           at android.app.ActivityThread.main(ActivityThread.java:5917) 
                                                                           at java.lang.reflect.Method.invoke(Native Method) 
                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) 
                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679) 

原因:

  1. 證書和證書密碼不匹配正歼。
  2. 使用了錯誤的證書辐马。證書類型不對。應(yīng)該使用bks類型證書加載的確實cer類型的

解決方法:

CLIENT_TRUST_PASSWORD是證書的密碼局义,必須與生成證書步驟里的設(shè)置的證書密碼一致喜爷。如下:

public static SSLSocketFactory getSSLSocketFactory(Context context) {
    final String CLIENT_TRUST_PASSWORD = "123456";//信任證書密碼,該證書默認密碼是changeit
    final String CLIENT_AGREEMENT = "TLS";//使用協(xié)議
    final String CLIENT_TRUST_KEYSTORE = "BKS";
    SSLContext sslContext = null;
    // ...
}

如果是cer類型證書萄唇,需要使用生成bks方法重新生成bsk類型證書檩帐。

坑2:java.io.IOException: Hostname 'xx.com' was not verified

原因:

服務(wù)器主機名認證失敗

解決方法:

1. 如果okhttpclient中有hostnameverify的配置,加上一個自定義的HostNameVerify,如下

((HttpsURLConnection) urlConnection).setHostnameVerifier(new HostnameVerifier() {
  @Override
  public boolean verify(String hostname, SSLSession session) {
    return true;
  }
});

2. 如果不需要HostNameVerify直接不設(shè)置就可以另萤。

//.hostnameVerifier(HTTPSUtils.getHostNameVerifier(hostUrls)) 注釋掉這句代碼

坑3:javax.net.ssl.SSLPeerUnverifiedException

原因:

SSL鏈接時主機名驗證失敗

解決方法:

//.hostnameVerifier(HTTPSUtils.getHostNameVerifier(hostUrls)) 注釋掉這句代碼

坑4:javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for cert

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for cert
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:333)
at okhttp3.internal.io.RealConnection.connectTls(RealConnection.java:239)
at okhttp3.internal.io.RealConnection.establishProtocol(RealConnection.java:196)
at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:171)
at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at okhttp3.RealCall.getResponse(RealCall.java:243)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:212)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:190)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
at okhttp3.RealCall.execute(RealCall.java:57)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.
at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80)
at rx.Subscriber.setProducer(Subscriber.java:211)
at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76)
at rx.Subscriber.setProducer(Subscriber.java:205)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.ja
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.ja
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:8666)
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:220
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecut
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust 
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324)
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:571)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:329)
... 35 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

原因:

使用了錯誤的證書湃密。證書驗證失敗。

解決

重新生成證書

后記

之前我是看的Tamic的做法四敞,不能走通泛源,不推薦使用它的那種做法。如果是使用它的那種做法忿危,出現(xiàn)錯誤达箍,請按照本文的做法,使用HTTPS癌蚁。

參考

http://www.cnblogs.com/lancer-ryn/p/5869696.html

http://www.reibang.com/p/9a6c204616d2

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末幻梯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子努释,更是在濱河造成了極大的恐慌碘梢,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伐蒂,死亡現(xiàn)場離奇詭異煞躬,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門恩沛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來在扰,“玉大人,你說我怎么就攤上這事雷客∶⒅椋” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵搅裙,是天一觀的道長皱卓。 經(jīng)常有香客問我,道長部逮,這世上最難降的妖魔是什么娜汁? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮兄朋,結(jié)果婚禮上掐禁,老公的妹妹穿的比我還像新娘。我一直安慰自己颅和,他們只是感情好傅事,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著融虽,像睡著了一般享完。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上有额,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天般又,我揣著相機與錄音,去河邊找鬼巍佑。 笑死茴迁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的萤衰。 我是一名探鬼主播堕义,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脆栋!你這毒婦竟也來了倦卖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤椿争,失蹤者是張志新(化名)和其女友劉穎怕膛,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秦踪,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡褐捻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年掸茅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柠逞。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡昧狮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出板壮,到底是詐尸還是另有隱情逗鸣,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布个束,位于F島的核電站慕购,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茬底。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一获洲、第九天 我趴在偏房一處隱蔽的房頂上張望阱表。 院中可真熱鬧,春花似錦贡珊、人聲如沸最爬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爱致。三九已至,卻和暖如春寒随,著一層夾襖步出監(jiān)牢的瞬間糠悯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工妻往, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留互艾,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓讯泣,卻偏偏與公主長得像纫普,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子好渠,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,110評論 25 707
  • 原文地址 http://blog.csdn.net/u012409247/article/details/4985...
    0fbf551ff6fb閱讀 3,521評論 0 13
  • 一昨稼、作用 不使用SSL/TLS的HTTP通信,就是不加密的通信拳锚。所有信息明文傳播假栓,帶來了三大風(fēng)險。 (1)竊聽風(fēng)險...
    XLsn0w閱讀 10,534評論 2 44
  • 服務(wù)器https配置 配置https操作說明文檔 1晌畅、查看服務(wù)器環(huán)境配置(tomcat和apache合并使用) 2...
    南京楊小兵閱讀 8,836評論 0 9
  • 萌寵奧斯卡開趴,帶上自己陪陪它 假使你想用90-130分鐘時間棋凳,經(jīng)歷掙扎走過大起大落拦坠,甚至穿越未知的時空,完成一場...
    藝厘米artcm閱讀 226評論 0 0