在维护一个很早之前同事开发的项目,之前的联网框架用的还是Volley,现在主流都是okHttp
或者是retrofit 框架了,坑爹的是公司后台接口由原来的Http网络请求协议改成了Https。
按理说只要把项目代码里面的请求接口改成Https即可。但是由于本人调试的是android 车机(汽车上的车机android 系统)时间撮 是2003年的 没有权限无法修改,本人知道,https 是证书加密协议请求。
将之前的Http请求改成Https的话 就会报:com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: null
错误。无语。
找了网上的一篇文章,大概知道了下,需要稍微修改下Volley 源码。
volley的网络请求 先要通过toolbox包下的Volley.java生成一个requestQueue.在requestQueue去分发请求,处理请求是使用HttpStack接口来完成的。看下面的代码Volley.java中的newRequestQueueInDisk。
我们来看下HurlStack这个类的构造大家就会发现其实volley可以支持https了,同样位于toolbox包下。
由此可以看出HurlStack 是支持HTTPS 只是在Volley.java生成对象时调用的是无参构造。所以 SSLSocketFactory并没有实例对象。
那么一种修改的方法是重写Volley.java newRequestQueueInDisk方法 调用第三个构造。又因为这三个构造最后调用的都是参数最多的那个所以也可以在第三个构造中直接默认生成SSLSocketFactory示例。但是我没有用这种方法。
我的实现方法是在toolbox中添加HTTPSTrustManager类(代码网上找的- -、),并对HurlStack的createConnetcion方法进行了小小的修改。
package com.android.volley.toolbox;
import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager;
public classHTTPSTrustManagerimplementsX509TrustManager{
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};
@Override
publicvoidcheckClientTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)throwsjava.security.cert.CertificateException{
// To change body of implemented methods use File | Settings | File // Templates. }
@Override
publicvoidcheckServerTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)throwsjava.security.cert.CertificateException{
// To change body of implemented methods use File | Settings | File // Templates. }
publicbooleanisClientTrusted(X509Certificate[] chain){
return true;
}
publicbooleanisServerTrusted(X509Certificate[] chain){
return true;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
publicstaticvoidallowAllSSL(){
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
publicbooleanverify(String arg0, SSLSession arg1){
// TODO Auto-generated method stub return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[] { new HTTPSTrustManager() };
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
createConnction方法的修改
其实就是添加了一个 HTTPSTrustManager类 并在createConnection中调用一下HTTPSTrustManager.allowAllSSL()。
网友评论