轉(zhuǎn)載請注明出處:http://www.itdecent.cn/p/37a73df2146a
本文出自Shawpoo的簡書
我的博客:CSDN博客
前言
在Android開發(fā)中,Okhttp想必大家都不陌生,一個(gè)處理網(wǎng)絡(luò)請求的開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架。
本人在開發(fā)過程中也用了很長一段時(shí)間了,但是基本請求的都是http接口。即使訪問https網(wǎng)站也都是綠色的,有個(gè)很特殊的大型購票網(wǎng)站則不是,所以本文主要介紹如何使用Okhttp訪問自簽名證書的https接口。而且公司自己服務(wù)接口也全部換成了https接口,在去年就說ios要強(qiáng)制更換https接口,不然appstore無法上架,最近好像也沒信了,估計(jì)是政策放寬了吧。不管怎樣,今天就拿這個(gè)大型購票網(wǎng)站舉例來說,使用Okhttp訪問購票網(wǎng)站。
獲取簽名證書
購票網(wǎng)站的簽名證書可以在官網(wǎng)上直接下載,或者點(diǎn)擊這里下載即可。srca.cer即為購票網(wǎng)站的簽名證書。
為了方便將簽名證書添加到OkHttp中,可以將簽名證書放在本地的assets文件夾下,為了便于管理我放在了assets/cers目錄下,在代碼中可以通過流的形式獲取到證書文件。
添加證書一般是在訪問接口之前添加,為了方便,我放在了Application中,這樣的話,在應(yīng)用啟動(dòng)的時(shí)候就會(huì)已經(jīng)將添加添加到了OkHttp中。
使用Okhttp訪問接口
- 使用Android Studio的話,直接添加Okhttp的依賴:
compile 'com.squareup.okhttp3:okhttp:3.3.1'
- 獲取簽名證書文件流
//獲取證書流
private void readHttpsCer() {
try {
InputStream is = getAssets().open("cers/srca.cer");
NetConfig.addCertificate(is); // 這里將證書讀取出來,,放在配置中byte[]里
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
- NetConfig相關(guān)代碼:
// 證書數(shù)據(jù)
private static List<byte[]> CERTIFICATES_DATA = new ArrayList<>();
/**
* 添加https證書
*
* @param inputStream
*/
public synchronized static void addCertificate(InputStream inputStream) {
Log.i(TAG, "#addCertificate inputStream = " + inputStream);
if (inputStream != null) {
try {
int ava = 0;// 數(shù)據(jù)當(dāng)次可讀長度
int len = 0;// 數(shù)據(jù)總長度
ArrayList<byte[]> data = new ArrayList<>();
while ((ava = inputStream.available()) > 0) {
byte[] buffer = new byte[ava];
inputStream.read(buffer);
data.add(buffer);
len += ava;
}
byte[] buff = new byte[len];
int dstPos = 0;
for (byte[] bytes : data) {
int length = bytes.length;
System.arraycopy(bytes, 0, buff, dstPos, length);
dstPos += length;
}
CERTIFICATES_DATA.add(buff);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* https證書
*
* @return
*/
public static List<byte[]> getCertificatesData() {
return CERTIFICATES_DATA;
}
- 編寫工具類,將證書添加到OkHttp中:
public static OkHttpClient createOkHttp() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
// 添加證書
List<InputStream> certificates = new ArrayList<>();
List<byte[]> certs_data = NetConfig.getCertificatesData();
// 將字節(jié)數(shù)組轉(zhuǎn)為數(shù)組輸入流
if (certs_data != null && !certs_data.isEmpty()) {
for (byte[] bytes : certs_data) {
certificates.add(new ByteArrayInputStream(bytes));
}
}
SSLSocketFactory sslSocketFactory = getSocketFactory(certificates);
if (sslSocketFactory != null) {
builder.sslSocketFactory(sslSocketFactory);
}
return builder.build();
}
/**
* 添加證書
*
* @param certificates
*/
private static SSLSocketFactory getSocketFactory(List<InputStream> certificates) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
try {
for (int i = 0, size = certificates.size(); i < size; ) {
InputStream certificate = certificates.get(i);
String certificateAlias = Integer.toString(i++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory
.generateCertificate(certificate));
if (certificate != null)
certificate.close();
}
} catch (IOException e) {
e.printStackTrace();
}
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
- 查看測試使用結(jié)果:
將自簽名證書添加到Okhttp中,通過創(chuàng)建的OkHttpClient對(duì)象,我們就可以訪問相關(guān)的Https接口服務(wù)了。
