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

转载 2016年05月31日 20:14:12

转自:http://blog.csdn.net/raptor/article/details/18898937

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

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

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

生成KeyStore

要验证自定义证书,首先要把证书编译到应用中去,这需要JSSE提供的keytool工具来生成KeyStore文件。参考《Java 安全套接字编程以及 keytool 使用最佳实践》,我试过了用JKS格式,但是结果连接失败,报错:Wrong version of key store。后来看了SO的这个帖才知道必须使用BKS的1.46版。更详细的内容参考这篇《Using a Custom Certificate Trust Store on Android》。

这里所谓的证书,实际上就是公钥,你可以从web服务器配置的.crt文件或.pem文件里获得。比如12306就直接提供了公钥证书下载,真是“服务周到”啊。

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

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

然后,你需要一个特定版本的JCE Provider,就是上面说过的那个SO帖里给的:http://www.bouncycastle.org/download/bcprov-jdk15on-146.jar 。注意,bouncycastle官网上目前发布的1.50版我试了一下不可用,不知道是不是我打开的方式不对,总之用这个1.46版的是没错的。

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

keytool -importcert -v -trustcacerts -alias cert12306 -file srca.cer \
-keystore cert12306.bks -storetype BKS \
-providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
-providerpath ./bcprov-jdk15on-146.jar -storepass pw12306

运行后将显示证书内容并提示你是否确认,按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/ 目录下。

  1. public class SSLCustomSocketFactory extends SSLSocketFactory {  
  2.     private static final String TAG = "SSLCustomSocketFactory";  
  3.   
  4.     private static final String KEY_PASS = "pw12306";  
  5.   
  6.     public SSLCustomSocketFactory(KeyStore trustStore) throws Throwable {  
  7.         super(trustStore);  
  8.     }  
  9.   
  10.     public static SSLSocketFactory getSocketFactory(Context context) {  
  11.         try {  
  12.             InputStream ins = context.getResources().openRawResource(R.raw.cert12306);  
  13.   
  14.             KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());  
  15.             try {  
  16.                 trustStore.load(ins, KEY_PASS.toCharArray());  
  17.             }  
  18.             finally {  
  19.                 ins.close();  
  20.             }  
  21.             SSLSocketFactory factory = new SSLCustomSocketFactory(trustStore);  
  22.             return factory;  
  23.         } catch (Throwable e) {  
  24.             Log.d(TAG, e.getMessage());  
  25.             e.printStackTrace();  
  26.         }  
  27.         return null;  
  28.     }  
  29. }  

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

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

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

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

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

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

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

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

最后再次放出本文例子程序的完整代码(Android Studio 0.4.2项目):https://bitbucket.org/raptorz/democert


相关文章推荐

在Android应用中使用自定义证书的HTTPS连接(上)

对于初次接触https有一定的帮助,本文属于转载篇。 原文地址:http://blog.csdn.net/raptor/article/details/18896375 前言 ...

在Android应用中使用自定义证书的HTTPS连接

因为这部分才是本文的重点,要说得详细一点,所以单独做成一篇来说。 安全地使用自定义证书的HTTPS连接方式 终极解决方案是:把证书编译到应用中去,由应用自己来验证证书。 生成KeyS...

在Android应用中使用自定义证书,CER转BKS

转换方法参考:http://blog.csdn.net/raptor/article/details/18898937首先要下载特定版本的JCE Provider包 http://www.bounc...

使用自定义证书并忽略验证的HTTPS连接Post请求方式的封装

使用自定义证书并忽略验证的HTTPS连接Post请求方式的封装 使用自定义证书并忽略验证的HTTPS连接方式 解决证书不被系统承认的方法,就是跳过系统校验。要跳过系统校验,就不能再使用系统标...

创建Material Design风格的Android应用--使用自定义动画

动画在Material Design设计中给用户反馈放用户点击时,并且在程序用户界面中提供连贯的视觉。Material主题为按钮(Button)和activity的转换提供了一些默认的动画,在andr...

android应用程序中使用自定义Toast控件

自定义Toast对于原生Toast的美中不足得到了美化。可以将自定义的ImageView和TextView控件添加到其中 先看看截图吧。 通过自定义实现之后,这是基本效果。 可以...

Android应用使用自定义字体

android 系统本身内置了一些字体,可以在程序中使用,并且支持在xml配置textView的时候进行修改字体的样式。支持字段为android:textStyle ,android:typeface...

日常开发——Android请求自定义证书的https

有时候为了app的数据安全,开发者会考虑使用https来进行数据传输。在安卓上,原生的HttpsURLConnection和WebView只支持那些得到安卓系统承认的证书的站点。如果请求那些使用未通过...

Android下OkHttp请求自定义HTTPS证书接口设置

在请求安全性高的接口时,我们可能会使用到HTTPS接口,HTTPS可以理解为HTTP+TLS,关于HTTPS具体是怎么工作的,可以看这篇文章:http://gold.xitu.io/entry/56e...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)