【第六篇】Volley之https相关
Volley之https信任所有证书实现:
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 { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException { } 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) { 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()); } }
代码中调用方法如下:
HttpsTrustManager.allowAllSSL();//主要是这行实现信任所有证书的操作 String tag_string_req = "string_req"; StringRequest strReq = new StringRequest(Request.Method.POST, your_https_url, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.d(TAG, "response :"+response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { VolleyLog.d(TAG, "Error: " + error.getMessage()); } }){ @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<String, String>(); params.put("username", "max"); params.put("password", "123456"); return params; } }; AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
信任指定的证书文件:
HurlStack代码里面有如下方法:
/** * @param urlRewriter Rewriter to use for request URLs * @param sslSocketFactory SSL factory to use for HTTPS connections * HurlStack这个类的构造大家就会发现其实volley可以支持https了,同样位于toolbox包下 */ public HurlStack(UrlRewriter urlRewriter, SSLSocketFactory sslSocketFactory) { mUrlRewriter = urlRewriter; mSslSocketFactory = sslSocketFactory; }
/** * Opens an {@link HttpURLConnection} with parameters. * @param url * @return an open connection * @throws IOException */ 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; }
在https协议的情况下,保证mSslSocketFactory 不为null,因此主要的问题是传进去sslSocketFactory这个参数。
stackoverflow上面有个产生这个内容的工具类:
private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) { final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0]; return new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return originalTrustManager.getAcceptedIssuers(); } public void checkClientTrusted(X509Certificate[] certs, String authType) { try { originalTrustManager.checkClientTrusted(certs, authType); } catch (CertificateException e) { e.printStackTrace(); } } public void checkServerTrusted(X509Certificate[] certs, String authType) { try { originalTrustManager.checkServerTrusted(certs, authType); } catch (CertificateException e) { e.printStackTrace(); } } } }; } private SSLSocketFactory getSSLSocketFactory_Certificate(String keyStoreType, int keystoreResId) throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = getResources().openRawResource(keystoreResId); Certificate ca = cf.generateCertificate(caInput); caInput.close(); if (keyStoreType == null || keyStoreType.length() == 0) { keyStoreType = KeyStore.getDefaultType(); } KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers()); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, wrappedTrustManagers, null); return sslContext.getSocketFactory(); } private SSLSocketFactory getSSLSocketFactory_KeyStore(String keyStoreType, int keystoreResId, String keyPassword) throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException { InputStream caInput = getResources().openRawResource(keystoreResId); // creating a KeyStore containing trusted CAs if (keyStoreType == null || keyStoreType.length() == 0) { keyStoreType = KeyStore.getDefaultType(); } KeyStore keyStore = KeyStore.getInstance(keyStoreType); keyStore.load(caInput, keyPassword.toCharArray()); // creating a TrustManager that trusts the CAs in the KeyStore String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers()); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, wrappedTrustManagers, null); return sslContext.getSocketFactory(); }
调用后面两个,就能获取SSLSocketFactory 内容,使用如下:
SSLSocketFactory sslSocketFactory = getSSLSocketFactory_KeyStore("BKS", R.raw.androidbksv1, "123456789");
SSLSocketFactory sslSocketFactory = getSSLSocketFactory_Certificate("BKS", R.raw.androidbksv1_cert);
http://stackoverflow.com/questions/32154115/android-volley-self-signed-https-trust-anchor-for-certification-path-not-found