标签:
其实在最早的版本里,Volley甚至是不支持https协议的,只能跑http,当然你也可以自己修改他的源码让他支持,如今volley的代码经过一些改进以后,
已经可以完美支持https协议了,无论是在2.3版本以上还是在2.3版本以下,大家可以尝试用volley去访问github 是成功的,但是你如果用volley去访问
12306这种类似的 用自定义证书的网站 就很容易失败。那我下面就把volley 代码稍作修改,让volley也可以完美支持自定义证书的https请求。
当然代码只是展示功能使用,你们可以用更优雅的方式 ----实现一个HttpStack,然后直接传你自定义好的stack即可。我这里图简便就写了个最简单
的演示代码。其实难倒是也不难,主要还是要考虑2.3版本以上和以下的两种情况。
第一步,把你的自定义证书 拷贝到res/raw/下。
第二步,稍微修改下volley的源码
1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.volley.toolbox; 18 19 import android.content.Context; 20 import android.content.pm.PackageInfo; 21 import android.content.pm.PackageManager.NameNotFoundException; 22 import android.net.http.AndroidHttpClient; 23 import android.os.Build; 24 import android.util.Log; 25 26 import com.android.volley.Network; 27 import com.android.volley.RequestQueue; 28 29 import org.apache.http.client.HttpClient; 30 import org.apache.http.conn.scheme.PlainSocketFactory; 31 import org.apache.http.conn.scheme.Scheme; 32 import org.apache.http.conn.scheme.SchemeRegistry; 33 import org.apache.http.impl.client.DefaultHttpClient; 34 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 35 import org.apache.http.params.BasicHttpParams; 36 import org.apache.http.params.HttpParams; 37 38 import java.io.File; 39 import java.io.IOException; 40 import java.io.InputStream; 41 import java.security.KeyManagementException; 42 import java.security.KeyStore; 43 import java.security.KeyStoreException; 44 import java.security.NoSuchAlgorithmException; 45 import java.security.UnrecoverableKeyException; 46 import java.security.cert.Certificate; 47 import java.security.cert.CertificateException; 48 import java.security.cert.CertificateFactory; 49 50 import javax.net.ssl.SSLContext; 51 import javax.net.ssl.SSLSocketFactory; 52 import javax.net.ssl.TrustManagerFactory; 53 54 public class Volley { 55 56 /** 57 * Default on-disk cache directory. 58 */ 59 private static final String DEFAULT_CACHE_DIR = "volley"; 60 61 private Context mContext; 62 63 /** 64 * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. 65 * 66 * @param context A {@link Context} to use for creating the cache dir. 67 * @param stack An {@link HttpStack} to use for the network, or null for default. 68 * @return A started {@link RequestQueue} instance. 69 */ 70 public static RequestQueue newRequestQueue(Context context, HttpStack stack, boolean selfSignedCertificate, int rawId) { 71 File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR); 72 73 String userAgent = "volley/0"; 74 try { 75 String packageName = context.getPackageName(); 76 PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0); 77 userAgent = packageName + "/" + info.versionCode; 78 } catch (NameNotFoundException e) { 79 } 80 81 if (stack == null) { 82 if (Build.VERSION.SDK_INT >= 9) { 83 if (selfSignedCertificate) { 84 stack = new HurlStack(null, buildSSLSocketFactory(context, rawId)); 85 } else { 86 stack = new HurlStack(); 87 } 88 } else { 89 // Prior to Gingerbread, HttpUrlConnection was unreliable. 90 // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html 91 if (selfSignedCertificate) 92 stack = new HttpClientStack(getHttpClient(context, rawId)); 93 else { 94 stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); 95 } 96 } 97 } 98 99 Network network = new BasicNetwork(stack); 100 101 RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network); 102 queue.start(); 103 104 return queue; 105 } 106 107 /** 108 * Creates a default instance of the worker pool and calls {@link RequestQueue#start()} on it. 109 * 110 * @param context A {@link Context} to use for creating the cache dir. 111 * @return A started {@link RequestQueue} instance. 112 */ 113 public static RequestQueue newRequestQueue(Context context) { 114 return newRequestQueue(context, null, false, 0); 115 } 116 117 private static SSLSocketFactory buildSSLSocketFactory(Context context, int certRawResId) { 118 KeyStore keyStore = null; 119 try { 120 keyStore = buildKeyStore(context, certRawResId); 121 } catch (KeyStoreException e) { 122 e.printStackTrace(); 123 } catch (CertificateException e) { 124 e.printStackTrace(); 125 } catch (NoSuchAlgorithmException e) { 126 e.printStackTrace(); 127 } catch (IOException e) { 128 e.printStackTrace(); 129 } 130 131 String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 132 TrustManagerFactory tmf = null; 133 try { 134 tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 135 tmf.init(keyStore); 136 137 } catch (NoSuchAlgorithmException e) { 138 e.printStackTrace(); 139 } catch (KeyStoreException e) { 140 e.printStackTrace(); 141 } 142 143 SSLContext sslContext = null; 144 try { 145 sslContext = SSLContext.getInstance("TLS"); 146 } catch (NoSuchAlgorithmException e) { 147 e.printStackTrace(); 148 } 149 try { 150 sslContext.init(null, tmf.getTrustManagers(), null); 151 } catch (KeyManagementException e) { 152 e.printStackTrace(); 153 } 154 155 return sslContext.getSocketFactory(); 156 157 } 158 159 private static HttpClient getHttpClient(Context context, int certRawResId) { 160 KeyStore keyStore = null; 161 try { 162 keyStore = buildKeyStore(context, certRawResId); 163 } catch (KeyStoreException e) { 164 e.printStackTrace(); 165 } catch (CertificateException e) { 166 e.printStackTrace(); 167 } catch (NoSuchAlgorithmException e) { 168 e.printStackTrace(); 169 } catch (IOException e) { 170 e.printStackTrace(); 171 } 172 if (keyStore != null) { 173 } 174 org.apache.http.conn.ssl.SSLSocketFactory sslSocketFactory = null; 175 try { 176 sslSocketFactory = new org.apache.http.conn.ssl.SSLSocketFactory(keyStore); 177 } catch (NoSuchAlgorithmException e) { 178 e.printStackTrace(); 179 } catch (KeyManagementException e) { 180 e.printStackTrace(); 181 } catch (KeyStoreException e) { 182 e.printStackTrace(); 183 } catch (UnrecoverableKeyException e) { 184 e.printStackTrace(); 185 } 186 187 HttpParams params = new BasicHttpParams(); 188 189 SchemeRegistry schemeRegistry = new SchemeRegistry(); 190 schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 191 schemeRegistry.register(new Scheme("https", sslSocketFactory, 443)); 192 193 ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); 194 195 196 return new DefaultHttpClient(cm, params); 197 } 198 199 private static KeyStore buildKeyStore(Context context, int certRawResId) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { 200 String keyStoreType = KeyStore.getDefaultType(); 201 KeyStore keyStore = KeyStore.getInstance(keyStoreType); 202 keyStore.load(null, null); 203 204 Certificate cert = readCert(context, certRawResId); 205 keyStore.setCertificateEntry("ca", cert); 206 207 return keyStore; 208 } 209 210 private static Certificate readCert(Context context, int certResourceID) { 211 InputStream inputStream = context.getResources().openRawResource(certResourceID); 212 Certificate ca = null; 213 214 CertificateFactory cf = null; 215 try { 216 cf = CertificateFactory.getInstance("X.509"); 217 ca = cf.generateCertificate(inputStream); 218 219 } catch (CertificateException e) { 220 e.printStackTrace(); 221 } 222 return ca; 223 } 224 }
第三步就是调用方式稍微做下修改:
其实主要就是你如果想使用自定义的证书https的时候 第三个参数记得传true,并且把证书也传进去,
当然写的优雅的话还是最好自己写个httpstack,然后volley的源码可以不用改,只需要在使用的时候
传自己的stack即可
Android 使Volley完美支持自定义证书的Https
标签:
原文地址:http://www.cnblogs.com/punkisnotdead/p/4788199.html