下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

如何在Android应用中使用自定义证书的HTTPS连接教程(下)

作者:课课家教育     来源: http://www.kokojia.com点击数:1053发布时间: 2016-05-26 14:19:17

标签: Android应用HTTPS安卓

  在《如何在Android应用中使用自定义证书的HTTPS连接教程(上)》这篇文章中已经简单介绍了使用自定义证书的HTTPS连接,那么本文主要详细讲解安全地使用自定义证书的HTTPS连接方式。

如何在Android应用中使用自定义证书的HTTPS连接教程(上)_Android应用_HTTPS_Java_课课家

       因为这部分才是本文的重点,要说得详细一点,所以单独做成一篇来说。

  安全地使用自定义证书的HTTPS连接方式

  终极解决方案是:把证书编译到应用中去,由应用自己来验证证书。

  生成KeyStore

  Keytool 是一个有效的安全钥匙和证书的管理工具。

  要验证自定义证书,首先要把证书编译到应用中去,这需要JSSE提供的keytool工具来生成KeyStore文件。这里所谓的证书,实际上就是公钥,你可以从web服务器配置的.crt文件或.pem文件里获得。

  还有一个比较简单的办法就是直接从浏览器里获得。比如用 FireFox 打开 https 链接,在地址栏顶部的小锁上点一下,然后点“更多信息……”-“查看证书”-“详细内容”-“导出”,即可将网站的X.509证书导出为一个文本文件。不过需要注意的是,这种方法只对某些HTTPS服务器有效——通常是使用自签名证书或是使用类似StarCom免费证书服务器,但是对 12306 或 google 这种的就无效了,具体原因不明。

  另外,不论是浏览器导出,还是服务器端获得,都是公钥证书,有两种格式:纯文本的.crt格式或是二进制的.cer格式,两种都可以用。

  把这两个文件放在一起,然后在这个目录下运行以下命令:

  运行后将显示证书内容并提示你是否确认,按Y回车确认即可。

  其中cert12306是个随便取的别名,供keytool管理时方便而已。srca.cer就是从12306网站下载的证书文件。cert12306.bks是生成的keyStore文件,注意,这个文件必须以JAVA变量名的方式命名,比如不能直接叫12306.bks,否则在加载资源时会因为名字不是合格的JAVA变量名而出错。 ./bcprov-jdk15on-146.jar 就是刚才下载的那个JCE Provider。最后pw12306是一个密码,用于确保KeyStore文件本身的安全。

  使用自定义keyStore实现连接

  以下就是这个方案的实现,基本上和TrustAll差不多,也是需要一个自定义的SSLSocketFactory,不过因为还是需要验证证书的,所以就不需要再定义TrustManager了,用系统内置的即可。不过为了读取KeyStore资源,需要增加一个Context参数。

  另外,前面生成的那个cert12306.bks文件要放到 res/raw/ 目录下。

public class SSLCustomSocketFactory extends SSLSocketFactory {
    private static final String TAG = "SSLCustomSocketFactory";

    private static final String KEY_PASS = "pw12306";

    public SSLCustomSocketFactory(KeyStore trustStore) throws Throwable {
        super(trustStore);
    }

    public static SSLSocketFactory getSocketFactory(Context context) {
        try {
            InputStream ins = context.getResources().openRawResource(R.raw.cert12306);

            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            try {
                trustStore.load(ins, KEY_PASS.toCharArray());
            }
            finally {
                ins.close();
            }
            SSLSocketFactory factory = new SSLCustomSocketFactory(trustStore);
            return factory;
        } catch (Throwable e) {
            Log.d(TAG, e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
}

  其中cert12306就是bks资源文件名,pw12306就是前面设置的密码。

  同样的,使用这个Factory注册到scheme:

schReg.register(new Scheme("https", SSLCustomSocketFactory.getSocketFactory(context), 443));

  现在,也可以成功地连接12306了,而且如此实现,基本上就能达到与用商业证书一样的安全性了。

  不过因为现在只使用了12306的证书,没有使用系统证书,所以只能连接12306,连GOOGLE都连接不了了。但这个问题好解决,只需要在连接不同网站时使用不同的HttpClient即可。或者自己实现一个混合验证的SSLSocketFactory。

  更加安全的双向认证的HTTPS连接方式

  当然,还有一种更安全的HTTPS通讯方式叫做双向认证。相对的,上面所说的全都是指服务端的单向认证:即只有服务器配置了证书,客户端只是使用服务器证书的公钥。而双向认证则是客户端也有一个由服务器签发的证书,这样服务器可以确认连接过来的客户端的身份,网络银行就使用了这种方式。

  双向认证的实现方式与本篇的实现方式差不多,只是在trustStore基础之上再增加一个keyStore,其内容为客户端证书,当然这个证书就是同时包含公钥和私钥的。因为搭建一个双向认证的服务器比较麻烦,一般应用也没必要,所以这里不再详细说明。

  本文主要介绍了安全地使用自定义证书的HTTPS连接方式,主要的内容从生成KeyStore,使用自定义keyStore实现连接和更加安全的双向认证的HTTPS连接方式三个方面做详细的讲解。更多的内容可以查找上文的代码链接。

赞(10)
踩(4)
分享到:
华为认证网络工程师 HCIE直播课视频教程