不同版本的TLS在Android中的支援情況
本文要解決的兩類問題:
1. 在Android4.1-Android5.0的系統上啟用TLSv1.1和TLSv1.2
2. java.lang.IllegalArgumentException: protocol TLSv1.1 is not supported
這兩個問題比較具有代表性,在群裡面討論的時候見過的次數也是最多的,因此有些人遇到的問題也許協議名稱不一樣,但是本質都是類似的。
問題原因和解決思路分析
從Android5.0行為變更可以看到Android5.0開始預設啟用了TLSv1.1和TLSv1.2,但是從Android4.1開始TLSv1.1和TLSv1.2其實就被支援了,只是預設沒有啟用而已。
我們最常用到的幾種協議是SSLv3、TLSv1、TLSv1.1和TLSv1.2,解決上面兩個問題要搞清楚的是這幾個協議在Android系統中被支援的情況和被啟用的情況,然後我們結合minSdkVersion和targetSdkVersion來選擇協議即可,不同版本的Android系統對上述協議的支援情況:
客戶端(SSLSocket)的支援情況:

服務端(SSLServerSocket)的支援情況:

資料來源:https://developer.android.com/reference/javax/net/ssl/SSLSocket
注意:這裡說的客戶端和服務端不是指Android端和JavaEE端/PHP端(還有Python、.NET等等),是指的在Android開發中的客戶端Socket(SSLSocket)和服務端Socket(SSLServerSocket)。
到這裡其實已經知道本文開始處的問題的原因了,TLSv1.1和TLSv1.2從Android4.1(Api級別16)開始才被支援,從Android4.4 Wear(Api級別20)才被啟用(手機是Android5.0,Api級別21),因此在不同版本的Android系統中會出現需要被啟用和啟用時報不被支援的問題。
我們可以寫一個TLS協議通用的相容類,在所有的Android中強制啟用已經被支援的所有協議,總結一下就是Android8.0及以上系統可以強制啟用TLSv1、TLSv1.1和TLSv1.2協議,Android4.1-Android7.1.1系統可以強制啟用SSLv3、TLSv1、TLSv1.1和TLSv1.2協議,其它版本系統可以強制啟用SSLv3和TLSv1協議。
綜上所述,如果開發者使用SSLv3協議,那麼minSdkVersion不限制,targetSdkVersion不高於25,並且需要儘快更新為TLSv1.1協議或者TLS1.2協議;如果開發者使用TLSv1.1協議或者TLSv1.2協議,那麼minSdkVersion應該不低於16,targetSdkVersion不限制;如果開發者使用TLSv1協議,那麼目前不受限制。
本文內容是目前本人瞭解到的知識,如果有其它更好解決方案或者本文沒有講到的要點請讀者在評論中告知!
程式碼實現
我們需要讓SSLSocket啟用對應的協議,程式碼對應的方法是:
1 SSLSocket#setEnabledProtocols(String[]);
因此我們需要先在不同版本的Android系統中生成不同的協議陣列:

SSLSocket是由SSLSocketFactory負責生成的,我們再寫一個SSLSocketFactory的包裝類,主要程式碼如下:


特別強調: 成員變數delegate強烈建議不要更改,原因是客戶端使用OkHttp(本人是使用okhttp-urlconnection時遇到的問題,沒有測試直接使用OkHttp是否存在問題)時,OkHttp會反射SSLSocketFactory的delegate變數來做一些操作,否則會出現Https請求失敗的問題。


以上學習方向我們有自己的高清思維方向導圖,架構師有自己講解的架構視訊分享(包括高階UI、效能優化、架構師課程、 NDK、混合式開發:ReactNative+Weex等多個Android技術知識的架構視訊資料和各種電子書籍閱讀),視訊資料獲取方式:關注+轉發+加群 185873940 領取!