Android 網路框架之OKhttp實現https請求
1.HTTPS定義
HTTPS全稱為Hyper Text Transfer Protocol over Secure Socket Layer或是Hypertext Transfer Protocol Secure
中文含義為“超文字傳輸安全協議” 。是以安全為目標的HTTP通道。簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL。 它是一個URI scheme(抽象識別符號體系),句法類同http:體系。用於安全的HTTP資料傳輸。https:URL表明它使用了HTTP,但HTTPS存在不同於HTTP的預設埠及一個加密/身份驗證層(在HTTP與TCP之間)。這個系統的最初研發由網景公司(Netscape)進行,並內建於其瀏覽器Netscape Navigator中,提供了身份驗證與加密通訊方法。現在它被廣泛用於全球資訊網上安全敏感的通訊,例如交易支付方面。
2.HTTPS和HTTP的區別
超文字傳輸協議HTTP協議被用於在Web瀏覽器和網站伺服器之間傳遞資訊。HTTP協議以明文方式傳送內容,不提供任何方式的資料加密,如果攻擊者擷取了Web瀏覽器和網站伺服器之間的傳輸報文,就可以直接讀懂其中的資訊,因此HTTP協議不適合傳輸一些敏感資訊,比如信用卡號、密碼等。
為了解決HTTP協議的這一缺陷,需要使用另一種協議:安全套接字層超文字傳輸協議HTTPS。為了資料傳輸的安全,HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證照來驗證伺服器的身份,併為瀏覽器和伺服器之間的通訊加密。
HTTPS和HTTP的區別主要為以下四點:
2.1.https協議需要到ca申請證照,一般免費證照很少,需要交費。
2.2.http是超文字傳輸協議,資訊是明文傳輸,https 則是具有安全性的ssl加密傳輸協議。
2.3.http和https使用的是完全不同的連線方式,用的埠也不一樣,前者是80,後者是443。
2.4.http的連線很簡單,是無狀態的;HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網路協議,比http協議安全。
3.HTTPS的工作原理
HTTPS在傳輸資料之前需要客戶端(瀏覽器)與服務端(網站)之間進行一次握手,在握手過程中將確立雙方加密傳輸資料的密碼資訊。握手過程的簡單描述如下:
瀏覽器將自己支援的一套加密演算法、HASH演算法傳送給網站。
網站從中選出一組加密演算法與HASH演算法,並將自己的身份資訊以證照的形式發回給瀏覽器。證照裡面包含了網站地址,加密公鑰,以及證照的頒發機構等資訊。
瀏覽器獲得網站證照之後,開始驗證證照的合法性,如果證照信任,則生成一串隨機數字作為通訊過程中對稱加密的祕鑰。然後取出證照中的公鑰,將這串數字以及HASH的結果進行加密,然後發給網站。
網站接收瀏覽器發來的資料之後,通過私鑰進行解密,然後HASH校驗,如果一致,則使用瀏覽器發來的數字串使加密一段握手訊息發給瀏覽器。
瀏覽器解密,並HASH校驗,沒有問題,則握手結束。接下來的傳輸過程將由之前瀏覽器生成的隨機密碼並利用對稱加密演算法進行加密。
握手過程中如果有任何錯誤,都會使加密連線斷開,從而阻止了隱私資訊的傳輸。
4.程式碼實現
1.使用okhttp實現https請求
實現https我們需要一份ca證照,購買的證照,格式為.pfx,帶有公鑰和私鑰,附帶一個密碼。還有一種格式為.cer的證照,這種證照是沒有私鑰的。
伺服器會將證照配置到tomcat中,客戶端則存放在本地,app啟動的時候載入進去。
.pfx格式和.cer格式的區別:
1.帶有私鑰的證照
由Public Key Cryptography Standards #12,PKCS#12標準定義,包含了公鑰和私鑰的二進位制格式的證照形式,以pfx作為證照檔案字尾名。
2.二進位制編碼的證照
證照中沒有私鑰,DER 編碼二進位制格式的證照檔案,以cer作為證照檔案字尾名。
3.Base64編碼的證照
證照中沒有私鑰,BASE64 編碼格式的證照檔案,也是以cer作為證照檔案字尾名。
2.程式碼
1.OkHttp設定
mOkHttpClient=new OkHttpClient.Builder()
.connectTimeout(DataConstant.nettimeout, TimeUnit.SECONDS)//連線時間
.readTimeout(DataConstant.nettimeout,TimeUnit.SECONDS)//讀時間
.writeTimeout(DataConstant.nettimeout,TimeUnit.SECONDS)//寫時間
.sslSocketFactory(sslSocketFactory,trustManager)//Https證照
.build();
即:.sslSocketFactory(sslSocketFactory,trustManager)//Https證照
通過sslSocketFactory方法設定https證照
2.獲取 SSLSocketFactory和 X509TrustManager 物件
2.1.下載相關證照放到asset目錄下
2.2.程式碼
public class MainApplication extends Application {
private static SSLSocketFactory sslSocketFactory;
private static X509TrustManager x509TrustManager;
@Override
public void onCreate() {
super.onCreate();
initx509TrustManagerAndsslSocketFactory();
}
/**
* 初始化
* */
private void initx509TrustManagerAndsslSocketFactory(){
InputStream inputStream = null;
try {
inputStream = getApplicationContext().getAssets().open("srca.cer"); //得到證照的輸入流
try {
if(null!=inputStream){
x509TrustManager = trustManagerForCertificates(inputStream);//以流的方式讀入證照
if(null!=x509TrustManager){
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{x509TrustManager}, null);
sslSocketFactory = sslContext.getSocketFactory();
}
}
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(null!=inputStream){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
MainApplication.setSslSocketFactory(sslSocketFactory);
MainApplication.setX509TrustManager(x509TrustManager);
}
/**
* 以流的方式新增信任證照
*/
private X509TrustManager trustManagerForCertificates(InputStream in) throws GeneralSecurityException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
if (certificates.isEmpty()) {
throw new IllegalArgumentException("expected non-empty set of trusted certificates");
}
// Put the certificates a key store.
char[] password = "password".toCharArray(); // Any password will work.
KeyStore keyStore = newEmptyKeyStore(password);
int index = 0;
for (Certificate certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificate);
}
// Use it to build an X509 trust manager.
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
}
/**
* 新增password
* @param password
* @return
* @throws GeneralSecurityException
*/
private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); // 這裡新增自定義的密碼,預設
InputStream in = null; // By convention, 'null' creates an empty key store.
keyStore.load(in, password);
return keyStore;
} catch (IOException e) {
throw new AssertionError(e);
}
}
public static SSLSocketFactory getSslSocketFactory() {
return sslSocketFactory;
}
public static void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
MainApplication.sslSocketFactory = sslSocketFactory;
}
public static X509TrustManager getX509TrustManager() {
return x509TrustManager;
}
public static void setX509TrustManager(X509TrustManager x509TrustManager) {
MainApplication.x509TrustManager = x509TrustManager;
}
}
注:這裡只是測試,用的12306以前的證照。現在的12306已近不需要這個證照了,使用OkHttp不用配置sslSocketFactory也能訪問。
相關文章
- Android網路請求(3) 網路請求框架OkHttpAndroid框架HTTP
- Android okHttp網路請求之Get/Post請求AndroidHTTP
- Android okHttp網路請求之Json解析AndroidHTTPJSON
- okhttp網路請求框架的簡單使用HTTP框架
- Android網路請求(終) 網路請求框架RetrofitAndroid框架
- Android okHttp網路請求之檔案上傳下載AndroidHTTP
- Android網路請求(4) 網路請求框架VolleyAndroid框架
- Android Http請求框架二:xUtils 框架網路請求AndroidHTTP框架
- Android okHttp網路請求之快取控制Cache-ControlAndroidHTTP快取
- OKHttp網路請求原理流程解析HTTP
- 初探計算機網路之HTTPS請求計算機網路HTTP
- java實現https請求JavaHTTP
- Android 網路框架 OKHttp 學習Android框架HTTP
- OkHttp、rxJava、Retrofit聯合網路請求(一)HTTPRxJava
- OkHttp、rxJava、Retrofit聯合網路請求(二)HTTPRxJava
- OkHttp關於https請求的設定HTTP
- Android探索之HttpURLConnection網路請求AndroidHTTP
- okhttp 原始碼解析 - 網路協議的實現 - 請求流程: 請求的傳送與響應的接收HTTP原始碼協議
- 淺析okHttp3的網路請求流程HTTP
- 網路請求框架對比框架
- OkHttp 3.7原始碼分析(二)——攔截器&一個實際網路請求的實現HTTP原始碼
- Retrofit和OkHttp實現 Android網路快取HTTPAndroid快取
- 網路請求優化之取消請求優化
- 從網路請求過程看OkHttp攔截器HTTP
- Retrofit+okhttp+Rxjava封裝網路請求工具類HTTPRxJava封裝
- Android網路請求(2)Android
- 網路請求框架之Retrofit2.0基本講解框架
- Android RxJava2+Retrofit2搭建網路請求框架AndroidRxJava框架
- Flutter 網路請求框架封裝Flutter框架封裝
- flutter dio網路請求封裝實現Flutter封裝
- 使用Retrofit+RxJava實現網路請求RxJava
- RxJava+Retrofit+Gson實現網路請求RxJava
- java|HttpsURLConnection實現https請求JavaHTTP
- Android 網路請求詳解Android
- 安卓okhttp3進行網路請求,一個簡單的登入頁面的實現安卓HTTP
- flutter網路請求框架dio基本使用Flutter框架
- MVVM框架的搭建(三)——網路請求MVVM框架
- 一步步封裝實現自己的網路請求框架封裝框架