前言
皇天不负有心人, 先感谢hongyang大哥的文章:
Android Https相关完全解析 当OkHttp遇到Https
说实话,如果你认真看完顶上那篇hongyang大哥的文章(我承认有点长,我也看了很久也不止一遍),你会发现,其实https就是用证书嘛,具体怎么弄别人都给你封装好了,你只要把证书放到 SSLSocketFactory 就行了
大家如果有需要,可以先看了后面的【关于证书】后再次看hongyang大哥的生成方法,因为我提到了几个我踩的坑,希望大家别踩到了
准备
- 单向验证(准备一对证书)、双向验证(准备两对证书)
- Volley(jar也好,compile也好)
- copy进来hongyang大哥的工具类HttpsUtils
操作
具体可以去看这里 https://github.com/mBigFlower/volley-utils/blob/master/volleyutil/src/main/java/com/flowerfat/volleyutil/https/HttpsUtils.java
我对hongyang大哥的HttpsUtils做了改动,现在返回SSLSocketFactory,然后在创建RequestQueue是就把它加进去
HurlStack hurlStack = new HurlStack(null, HttpsUtils.initCertificates(bksFile, password, certificates));
mRequestQueue = Volley.newRequestQueue(context, hurlStack);
原理
用过Volley的都知道,我们发起网络请求前,会先创建一个请求队列
RequestQueue mRequestQueue = Volley.newRequestQueue(context);
我们进入newRequestQueue所在的类Volley去看看咋回事儿
public static RequestQueue newRequestQueue(Context context) {
return newRequestQueue(context, null);
}
public static RequestQueue newRequestQueue(Context context, HttpStack stack)
{
return newRequestQueue(context, stack, -1);
}
public static RequestQueue newRequestQueue(Context context, HttpStack stack, int maxDiskCacheBytes) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue;
if (maxDiskCacheBytes <= -1)
{
// No maximum size specified
queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
}
else
{
// Disk cache size specified
queue = new RequestQueue(new DiskBasedCache(cacheDir, maxDiskCacheBytes), network);
}
queue.start();
return queue;
}
public static RequestQueue newRequestQueue(Context context) {
return newRequestQueue(context, null);
}
其实这里面默认的HttpStack是为null的,那HttpStack是什么?我们来看第三个构造函数里的这句话
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
额,这个判断我也是醉了,我们可以直接忽略4.0以下吧?那直接看 new HurlStack();
public HurlStack() {
this(null);
}
public HurlStack(UrlRewriter urlRewriter) {
this(urlRewriter, null);
}
public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {
mUrlRewriter = urlRewriter;
mSslSocketFactory = sslSocketFactory;
}
看到没,看到没?那个SSLSocketFactory !
没错,如果你看过hongyang大哥的文章,你就会直到,okhttp就是通过这个把证书信任进去的
关于证书
在跟服务器联调前,我们可以先验证下我们的方法是否正确
具体的操作就去看洪洋大哥的文章吧,我就不再墨迹了。但是有几个坑需要注意一下:
- 在生成证书的时候,最好再后面加上这个:-ext san=ip:192.168.56.1 后面的ip地址换成道友你们电脑的ip,不然可能会出现 hostname 192…….. not verified的错误
- 下图中,那些是一起的,别看是四行,当初我就脑残的只输入第一行。。。
- 在双向验证证书中,jks转bks,使用portecle时,这句话“解压后,里面包含bcprov.jar文件,使用jave -jar bcprov.jar即可打开GUI界面。” ,其实应该是java -jar portecle.jar
- 大家使用tomcat的时候,我不造为啥有的时候下载下来的zip不能用,start到一半就没有下文了。可能是配置的问题,大家也可以下载安装包哈,今天我本子就是用安装包的。(如果你用的是zip解压的,打开tomcat7w.exe前,可能需要在命令行中输入server.bat install)
源码
源码都在 https://github.com/mBigFlower/volley-utils 里,这是我自己封装的Volley,对于证书的配置在VolleyUtils里的init()