This article shows how to use volley with OkHttp and security your api with https. 本文可以在简书浏览。
Volley 默认根据 Android 系统版本使用不同的 Http 传输协议实现. 3.0 以上使用HttpUrlConnection, 2.3 以下使用 ApacheHttpStack, 参考Android Http Client.
OkHttp 相较于其它的实现有以下的优点:
因此使用 OkHttp 作为替代是好的选择.
首先用 OkHttp 实现一个新的 HurlStack
用于构建 Volley 的 requestQueue.
public class OkHttpStack extends HurlStack {
private OkHttpClient okHttpClient;
/**
* Create a OkHttpStack with default OkHttpClient.
*/
public OkHttpStack() {
this(new OkHttpClient());
}
/**
* Create a OkHttpStack with a custom OkHttpClient
* @param okHttpClient Custom OkHttpClient, NonNull
*/
public OkHttpStack(OkHttpClient okHttpClient) {
this.okHttpClient = okHttpClient;
}
@Override
protected HttpURLConnection createConnection(URL url) throws IOException {
OkUrlFactory okUrlFactory = new OkUrlFactory(okHttpClient);
return okUrlFactory.open(url);
}
}
然后使用 OkHttpStack 创建新的 Volley requestQueue.
requestQueue = Volley.newRequestQueue(getContext(), new OkHttpStack());
requestQueue.start();
这样就行了.
作为一个有节操的开发者应该使用 Https 来保护用户的数据, Android 开发者网站上文章Security with HTTPS and SSL做了详尽的阐述.
OkHttp 自身是支持 Https 的. 参考文档 OkHttp Https, 直接使用上面的 OkHttpStack
就可以了, 但是如果遇到服务器开发哥哥使用了自签名的证书(不要问我为什么要用自签名的), 就无法正常访问了.
网上有很多文章给出的方案是提供一个什么事情都不做的TrustManager
跳过 SSL
的验证, 这样做很容受到攻击, Https 也就形同虚设了.
我采用的方案是将自签名的证书打包入 APK 加入信任.
好处:
以最著名的自签名网站12306为例说明
导出证书
echo | openssl s_client -connect kyfw.12306.cn:443 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > kyfw.12306.cn.pem
将证书转为 bks 格式 下载最新的bcprov-jdk, 执行下面的命令. storepass 是导出密钥文件的密码.
keytool -importcert -v \
-trustcacerts \
-alias 0 \
-file <(openssl x509 -in kyfw.12306.cn.pem) \
-keystore kyfw.bks -storetype BKS \
-providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
-providerpath ./bcprov-jdk16-1.46.jar \
-storepass asdfqaz
将导出的 kyfw.bks 文件放入 res/raw 文件夹下.
创建 SelfSignSslOkHttpStack
// A HttpStack implement witch can verify specified self-signed certification.
public class SelfSignSslOkHttpStack extends HurlStack {
private OkHttpClient okHttpClient;
private Map<String, SSLSocketFactory> socketFactoryMap;
// Create a OkHttpStack with default OkHttpClient.
public SelfSignSslOkHttpStack(Map<String, SSLSocketFactory> factoryMap) {
this(new OkHttpClient(), factoryMap);
}
// Create a OkHttpStack with a custom OkHttpClient
// @param okHttpClient Custom OkHttpClient, NonNull
public SelfSignSslOkHttpStack(OkHttpClient okHttpClient, Map<String, SSLSocketFactory> factoryMap) {
this.okHttpClient = okHttpClient;
this.socketFactoryMap = factoryMap;
}
@Override
protected HttpURLConnection createConnection(URL url) throws IOException {
if ("https".equals(url.getProtocol()) && socketFactoryMap.containsKey(url.getHost())) {
HttpsURLConnection connection = (HttpsURLConnection) new OkUrlFactory(okHttpClient).open(url);
connection.setSSLSocketFactory(socketFactoryMap.get(url.getHost()));
return connection;
} else {
return new OkUrlFactory(okHttpClient).open(url);
}
}
}
然后用 SelfSignSslOkHttpStack
创建 Volley 的 RequestQueue.
String[] hosts = {"kyfw.12306.cn"};
int[] certRes = {R.raw.kyfw};
String[] certPass = {"asdfqaz"};
socketFactoryMap = new Hashtable<>(hosts.length);
for (int i = 0; i < certRes.length; i++) {
int res = certRes[i];
String password = certPass[i];
SSLSocketFactory sslSocketFactory = createSSLSocketFactory(context, res, password);
socketFactoryMap.put(hosts[i], sslSocketFactory);
}
HurlStack stack = new SelfSignSslOkHttpStack(socketFactoryMap);
requestQueue = Volley.newRequestQueue(context, stack);
requestQueue.start();
done
(Note: This article’s original links is here )