zoukankan      html  css  js  c++  java
  • Android 使Volley完美支持自定义证书的Https

    其实在最早的版本里,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即可

  • 相关阅读:
    es6基础系列二:Number
    es6基础系列一:let和const
    linux常用命令
    input 事件与汉字输入法:使用compositionend事件解决
    正则表达式
    php 调试环境配置(mac)
    前端实习生:10个月的总结
    人生路:程序员、飞行员?
    科三流水账
    阻止pc端浏览器缩放js代码
  • 原文地址:https://www.cnblogs.com/punkisnotdead/p/4788199.html
Copyright © 2011-2022 走看看