转载请标明出处:【http://blog.youkuaiyun.com/hlglinglong/article/details/42553829】
1.概述
Volley框架相信大家都不陌生了,具体的介绍就不多说了,自己百度~
但是在实际的使用中,我们服务端的接口大多使用https的方式进行访问,volley默认不支持https的访问方式。
这就需要我们来手动的修改来是volley可以支持volley
2.问题分析
其实Volley可以支持HTTPS,但是框架中默认没有加上去我们可以修改一小部分源码来实现这以功能。
volley的网络请求 先要通过toolbox包下的Volley.java生成一个requestQueue.在requestQueue去分发请求,处理请求是使用HttpStack接口来完成的。看下面的代码Volley.java中的newRequestQueueInDisk
<span style="font-family:SimSun;"><span style="font-family:SimSun;font-size:14px;"><strong> /**
* Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it.
*
* @param context A {@link Context} to use for creating the cache dir.
* @param stack An {@link HttpStack} to use for the network, or null for default.
* @return A started {@link RequestQueue} instance.
*/
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
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 = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
</strong></span></span>
我们来看下HurlStack这个类的构造大家就会发现其实volley可以支持https了,同样位于toolbox包下
<span style="font-family:SimSun;">public HurlStack() {
this(null);
}
/**
* @param urlRewriter Rewriter to use for request URLs
*/
public HurlStack(UrlRewriter urlRewriter) {
this(urlRewriter, null);
}
/**
* @param urlRewriter Rewriter to use for request URLs
* @param sslSocketFactory SSL factory to use for HTTPS connections
*/
public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {
mUrlRewriter = urlRewriter;
mSslSocketFactory = sslSocketFactory;
}</span>
<span style="font-family:SimSun;"> private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {
HttpURLConnection connection = createConnection(url);
int timeoutMs = request.getTimeoutMs();
connection.setConnectTimeout(timeoutMs);
connection.setReadTimeout(timeoutMs);
connection.setUseCaches(false);
connection.setDoInput(true);
// use caller-provided custom SslSocketFactory, if any, for HTTPS
if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {
((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
}
return connection;
}</span>
由此可以看出HurlStack 是支持HTTPS 只是在Volley.java生成对象时调用的是无参构造。所以 SSLSocketFactory并没有实例对象。导致默认Volley不支持https请求
3.解决方案
1)既然volley框架里面有https请求方式,只不过没有调用,那么一种修改的方法是重写Volley.java newRequestQueueInDisk方法 调用第三个构造。又因为这三个构造最后调用的都是参数最多的那个所以也可以在第三个构造中直接默认生成SSLSocketFactory示例。但是我没有用这种方法。
2)
createConnction方法的修改
其实就是添加了一个 HTTPSTrustManager类 并在createConnection中调用一下HTTPSTrustManager.allowAllSSL()。
在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 class HTTPSTrustManager implements X509TrustManager {
- private static TrustManager[] trustManagers;
- private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};
- @Override
- public void checkClientTrusted(
- java.security.cert.X509Certificate[] x509Certificates, String s)
- throws java.security.cert.CertificateException {
- // To change body of implemented methods use File | Settings | File
- // Templates.
- }
- @Override
- public void checkServerTrusted(
- java.security.cert.X509Certificate[] x509Certificates, String s)
- throws java.security.cert.CertificateException {
- // To change body of implemented methods use File | Settings | File
- // Templates.
- }
- public boolean isClientTrusted(X509Certificate[] chain) {
- return true;
- }
- public boolean isServerTrusted(X509Certificate[] chain) {
- return true;
- }
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return _AcceptedIssuers;
- }
- public static void allowAllSSL() {
- HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
- @Override
- public boolean verify(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方法的修改
- protected HttpURLConnection createConnection(URL url) throws IOException {
- //如果请求是https请求那么就信任所有SSL
- <span style="white-space:pre"> </span>if (url.toString().contains("https")) {
- HTTPSTrustManager.allowAllSSL();
- }
- return (HttpURLConnection) url.openConnection();
- }
3)
不修改volley框架代码,在创建Request请求之前设置,如下
<span style="font-family:SimSun;">HttpTrustManager.allowAllSSL();
mStringRequest = new StringRequest(Request.Method.POST,url,getDefaultSuccessListener(),
mErrorListener){
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return params;
}
};
mRequestQueue.add(mStringRequest);</span>
同样可以达到效果。