安卓与HTTPS

公司的项目,出于安全考虑,使用https的方式来交互数据。这段时间也是被https折磨了一下,以一个新手的角度记录下Android下https的相关东西。

首先,https是需要证书才能访问到的,对于开发者来说,这个证书后台会提供的。拿到证书之后,网络请求要加上这个证书的信息有两种方式:

1、第一种就是把证书文件放置在assets下面,然后在Application的onCreate方法内加上如下代码来读取且设置证书

try {
    OkHttpClientManager.getInstance().setCertificates(getAssets().open("abc.cer"));
} catch (IOException e) {
    e.printStackTrace();
}
这里网络请求使用的是OkHttp,“abc.cer”是证书的名字,setCertificates方法如下:

public void setCertificates(InputStream... certificates) {
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        int index = 0;
        for (InputStream certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));

            try {
                if (certificate != null)
                    certificate.close();
            } catch (IOException e) {
            }
        }

        SSLContext sslContext = SSLContext.getInstance("TLS");

        TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

        trustManagerFactory.init(keyStore);
        sslContext.init(
                null,
                trustManagerFactory.getTrustManagers(),
                new SecureRandom()
        );
        mOkHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
2、如果不想放证书进入,可以读取出来证书的内容,然后用如下方式

final String CER_XXX = "aaaaaa"; // 证书内容
try {
    OkHttpClientManager.getInstance().setCertificates(new Buffer()
            .writeUtf8(CER_XXX)
            .inputStream());
} catch (IOException e) {
    e.printStackTrace();
}

正常情况下,使用以上任意一种方式之后,就能请求到https接口的数据了。但是作为新手总是会遇到坑... 笔者就发现,测试环境的https完全正常,但是正式环境的https却访问不到数据了,证书当然是正确的,那么是为什么呢?

原来,大多数情况下,服务器所使用的根证书是自签名的,或者签名机构不在设备的信任证书列表中,这样使用httpclient进行https连接就会失败。解决这个问题的办法有两种,一是在发起https连接之前将服务器证书加到httpclient的信任证书列表中,这个相对来说比较复杂一些,很容易出错;另一种办法是让httpclient信任所有的服务器证书,这种办法相对来说简单很多,但安全性则差一些,但在某些场合下有一定的应用场景。

好吧,笔者还是选择后者好了,在加了如下代码信任所有服务器证书之后,问题解决。奋斗

mOkHttpClient.setHostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
});



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值