Volley支持https的3种方法小结

最近遇到网络安全方面的问题,所以要使用https,由于在工程中使用了Volley,所以对Volley的https做了一些研究,当然大部分是参考的网络上一些前辈们的成果,自己进行一下总结:

https涉及到证书的认证方式,我就按认证的类型来说明:

1,全部信任证书;
2,信任指定证书;
3,信任系统提供的证书(CA颁发);

1,全部信任证书

添加HTTPSTrustManager类,如下:

import android.content.Context;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
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.TrustManagerFactory;
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.
    }

    @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());
    }
}

再在创建 RequestQueue 时,添加一句:

HTTPSTrustManager.allowAllSSL();//信任所有证书
RequestQueue mQueue = Volley.newRequestQueue(getActivity());

后面就可以根据需要添加请求了:

mQueue.add(request);

2,信任指定证书

先要获取到证书,我们可以放到assert目录下,例如这里使用的证书的文件名为“root.crt”。
然后通过如下函数来读取,并返回SSLSocketFactory:

    //生成SSLSocketFactory
    private SSLSocketFactory initSSLSocketFactory() {
        //生成证书:Certificate
        CertificateFactory cf = null;
        SSLSocketFactory factory = null;
        try {
            cf = CertificateFactory.getInstance("X.509");
            InputStream caInput = getActivity().getAssets().open("root.crt");
            Certificate ca = null;
            try {
                ca = cf.generateCertificate(caInput);
            } finally {
                try {
                    caInput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            //初始化公钥:keyStore
            String keyType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            //初始化TrustManagerFactory
            String algorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory managerFactory = TrustManagerFactory.getInstance(algorithm);
            managerFactory.init(keyStore);

            //初始化sslContext
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, managerFactory.getTrustManagers(), null);
            factory = sslContext.getSocketFactory();

        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        return factory;
    }

然后,在创建 RequestQueue 时,按如下方式来执行:

//生成SSLSocketFactory
SSLSocketFactory sslSocketFactory = initSSLSocketFactory();

//HurlStack两个参数默认都是null,如果传入SSLSocketFactory,那么会以Https的方式来请求网络
HurlStack stack = new HurlStack(null, sslSocketFactory);

//传入处理Https的HurlStack
mQueue = Volley.newRequestQueue(this.getActivity(),stack);

后面添加请求的方法是一样的:

mQueue.add(request);

3,信任系统提供的证书(CA颁发)

先了解下什么是系统提供的证书,看看下面的说明:
HTTPS通信所用到的证书由CA提供,需要在服务器中进行相应的设置才能生效。另外在我们的客户端设备中,只要访问的HTTPS的网站所用的证书是可信CA根证书签发的,如果这些CA又在浏览器或者操作系统的根信任列表中,就可以直接访问。
也就是说,Android系统有一个根信任列表,若我们的证书是这个列表中的某个根证书的子证书,就不需要特别指定了。

通常情况,就是使用https,而不做任何特别指定,就是使用系统的证书了。
可是Volley直接访问https,我遇到了问题:
最初我的工程,由http直接切换到https时,是不能运行的,通过上面的方法,信任所有证书,或者信任指定证书,可以进行https的访问了。
但是前面两种方法各有一些缺陷:

全部信任证书:不安全,Google也不推荐,据我个人了解,就是防不住中间人攻击。

信任指定证书:这种方式是可以防止中间人攻击的。
但是问题可能会出在App上:这个证书直接放在app中,若是被反编译出来,证书会被人获得,仍然会导致某些风险;
另外就是,若是指定的证书变化了,就需要更换所有的app,在用户量较大的情况下,这几乎是不可能完成的任务。

所以,若是在可能的情况下,最好是使用正式认证的证书。这时,也不需要我们去指定证书了,Android系统就已经维护了一套了。

怎么实现呢?经过一番搜索,有人说新版本的Volley已经支持https了。难道是版本的问题?

我从如下地址下载了一个较新的包(V1.0.19):
http://mvnrepository.com/artifact/com.mcxiaoke.volley/library
然后替换了系统中的旧的jar包,果然好了!

这时,使用Volley就是普通的操作方式:
先创建 RequestQueue :

RequestQueue mQueue = Volley.newRequestQueue(getActivity());

后面就是根据需要添加请求了:

mQueue.add(request);

最后总结一下:

1,全部信任证书:毕竟是https,要比http安全多了,但是还存在被中间人攻击的风险;
2,信任指定证书:保证了网络传输链路的安全,但是App本身存在泄漏证书的风险。另外,更换证书时比较麻烦。
3,信任系统提供的证书(CA颁发);这种方式最安全,但是可能需要花钱。也可以找些免费的证书,但是使用期限可能有较大的限制。
这三种方式各有特色,具体采用哪种方式,还是需要根据项目的实际情况来确定。

参考:

http://www.lai18.com/content/1040213.html
http://www.cnblogs.com/punkisnotdead/p/4788199.html

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值