Volley框架支持HTTPS请求。

第一次写帖子,嘿嘿。

最近了解到google2013IO大会出了个网络框架,正好项目也需要用到,就看了下。

最后发现接口都是HTTPS的,但是Volley默认是不支持HTTPS,网上找了好久,都没有对Volley HTTPS请求做解答。

所以分享下心得。

bvin大神已经分析框架的帖子 在下面的传送:

谷歌Volley网络框架讲解——第一篇

谷歌Volley网络框架讲解——Network及其实现类

谷歌Volley网络框架讲解——HttpStack及其实现类

具体框架的安装及使用我是参照下面文章:

http://www.cnblogs.com/xyzlmn/p/3360485.html

 

通过前面的内容可以使大家对Volley有所了解。下面就开始讲支持HTTPS的实现。

其实Volley可以支持HTTPS,但是框架中默认没有加上去我们可以修改一小部分源码来实现这以功能。

volley的网络请求 先要通过toolbox包下的Volley.java生成一个requestQueue.在requestQueue去分发请求,处理请求是使用HttpStack接口来完成的。看下面的代码Volley.java中的newRequestQueueInDisk

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public static RequestQueue newRequestQueueInDisk(Context context, String dir, HttpStack stack) {  
  2.         File cacheDir = new File(dir, DEFAULT_CACHE_DIR);  
  3.   
  4.         String userAgent = "volley/0";  
  5.         try {  
  6.             String packageName = context.getPackageName();  
  7.             PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);  
  8.             userAgent = packageName + "/" + info.versionCode;  
  9.         } catch (NameNotFoundException e) {  
  10.         }  
  11.   
  12.         if (stack == null) {  
  13.         //2.3及以上版本使用HurlStack来处理请求  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1.         if (Build.VERSION.SDK_INT >= 9) {  
  2.             stack = new HurlStack();  
  3.         } else {  
  4.             // Prior to Gingerbread, HttpUrlConnection was unreliable.  
  5.             // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html  
  6.             stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));  
  7.         }  
  8.     }  
  9.   
  10.     Network network = new BasicNetwork(stack);  
  11.   
  12.     RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);  
  13.     queue.start();  
  14.   
  15.     return queue;  
  16. }  


我们来看下HurlStack这个类的构造大家就会发现其实volley可以支持https了,同样位于toolbox包下

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public HurlStack() {  
  2.        this(null);  
  3.    }  
  4.   
  5.    /** 
  6.     * @param urlRewriter Rewriter to use for request URLs 
  7.     */  
  8.    public HurlStack(UrlRewriter urlRewriter) {  
  9.        this(urlRewriter, null);  
  10.    }  
  11.   
  12.    /** 
  13.     * @param urlRewriter Rewriter to use for request URLs 
  14.     * @param sslSocketFactory SSL factory to use for HTTPS connections 
  15.     */  
  16.    public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) {  
  17.        mUrlRewriter = urlRewriter;  
  18.        mSslSocketFactory = sslSocketFactory;  
  19.    }  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {  
  2.        HttpURLConnection connection = createConnection(url);  
  3.   
  4.        int timeoutMs = request.getTimeoutMs();  
  5.        connection.setConnectTimeout(timeoutMs);  
  6.        connection.setReadTimeout(timeoutMs);  
  7.        connection.setUseCaches(false);  
  8.        connection.setDoInput(true);  
  9.   
  10.       <span style="color:#ff6600;"> </span>// use caller-provided custom SslSocketFactory, if any, for HTTPS  
  11.        if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {  
  12.            ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);  
  13.        }  
  14.   
  15.        return connection;  
  16.    }  


由此可以看出HurlStack 是支持HTTPS 只是在Volley.java生成对象时调用的是无参构造。所以 SSLSocketFactory并没有实例对象。

那么一种修改的方法是重写Volley.java newRequestQueueInDisk方法 调用第三个构造。又因为这三个构造最后调用的都是参数最多的那个所以也可以在第三个构造中直接默认生成SSLSocketFactory示例。但是我没有用这种方法。

我的实现方法是在toolbox中添加HTTPSTrustManager类(代码网上找的- -、),并对HurlStack的createConnetcion方法进行了小小的修改。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. package com.android.volley.toolbox;  
  2.   
  3. import java.security.KeyManagementException;  
  4. import java.security.NoSuchAlgorithmException;  
  5. import java.security.SecureRandom;  
  6. import java.security.cert.X509Certificate;  
  7.   
  8. import javax.net.ssl.HostnameVerifier;  
  9. import javax.net.ssl.HttpsURLConnection;  
  10. import javax.net.ssl.SSLContext;  
  11. import javax.net.ssl.SSLSession;  
  12. import javax.net.ssl.TrustManager;  
  13. import javax.net.ssl.X509TrustManager;  
  14.   
  15. public class HTTPSTrustManager implements X509TrustManager {  
  16.   
  17.     private static TrustManager[] trustManagers;  
  18.     private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};  
  19.   
  20.     @Override  
  21.     public void checkClientTrusted(  
  22.             java.security.cert.X509Certificate[] x509Certificates, String s)  
  23.             throws java.security.cert.CertificateException {  
  24.         // To change body of implemented methods use File | Settings | File  
  25.         // Templates.  
  26.     }  
  27.   
  28.     @Override  
  29.     public void checkServerTrusted(  
  30.             java.security.cert.X509Certificate[] x509Certificates, String s)  
  31.             throws java.security.cert.CertificateException {  
  32.         // To change body of implemented methods use File | Settings | File  
  33.         // Templates.  
  34.     }  
  35.   
  36.     public boolean isClientTrusted(X509Certificate[] chain) {  
  37.         return true;  
  38.     }  
  39.   
  40.     public boolean isServerTrusted(X509Certificate[] chain) {  
  41.         return true;  
  42.     }  
  43.   
  44.     @Override  
  45.     public X509Certificate[] getAcceptedIssuers() {  
  46.         return _AcceptedIssuers;  
  47.     }  
  48.   
  49.     public static void allowAllSSL() {  
  50.         HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {  
  51.   
  52.             @Override  
  53.             public boolean verify(String arg0, SSLSession arg1) {  
  54.                 // TODO Auto-generated method stub  
  55.                 return true;  
  56.             }  
  57.   
  58.         });  
  59.   
  60.         SSLContext context = null;  
  61.         if (trustManagers == null) {  
  62.             trustManagers = new TrustManager[] { new HTTPSTrustManager() };  
  63.         }  
  64.   
  65.         try {  
  66.             context = SSLContext.getInstance("TLS");  
  67.             context.init(null, trustManagers, new SecureRandom());  
  68.         } catch (NoSuchAlgorithmException e) {  
  69.             e.printStackTrace();  
  70.         } catch (KeyManagementException e) {  
  71.             e.printStackTrace();  
  72.         }  
  73.   
  74.         HttpsURLConnection.setDefaultSSLSocketFactory(context  
  75.                 .getSocketFactory());  
  76.     }  
  77.   
  78. }  


createConnction方法的修改

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. protected HttpURLConnection createConnection(URL url) throws IOException {  
  2.     //如果请求是https请求那么就信任所有SSL  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. <span style="white-space:pre">  </span>if (url.toString().contains("https")) {  
  2.               HTTPSTrustManager.allowAllSSL();  
  3.         }  
  4.         return (HttpURLConnection) url.openConnection();  
  5.     }  



其实就是添加了一个 HTTPSTrustManager类 并在createConnection中调用一下HTTPSTrustManager.allowAllSSL()。

就这么简单= =、

还想发点使用心得,感觉这个有点多了,能看完我这些废话的人已经很有耐心了,所以就不折磨大家了。下次

原文地址:https://www.cnblogs.com/xiaorenwu702/p/4699891.html