MyException - 我的异常网
当前位置:我的异常网» Android » Https系列之4:https的SSL证书在Android端基于okhtt

Https系列之4:https的SSL证书在Android端基于okhttp,Retrofit的使用

www.MyException.Cn  网友分享于:2013-10-08  浏览:0次
Https系列之四:https的SSL证书在Android端基于okhttp,Retrofit的使用

Https系列会在下面几篇文章中分别作介绍:

一:https的简单介绍及SSL证书的生成
二:https的SSL证书在服务器端的部署,基于tomcat,spring boot
三:让服务器同时支持http、https,基于spring boot
四:https的SSL证书在Android端基于okhttp,Retrofit的使用

所有文章会优先在:
微信公众号“颜家大少”中发布
转载请标明出处


先来回顾一下

前面已分别介绍了https,SSL证书的生成,并完成了服务器端的https的部署
并提到一个重要的用于客户端的证书:公钥证书
在前面文章中,自签名SSL证书对应的公钥证书为:mycer.cer(当然这名字是自己随便定的);在阿里云申请的CA证书中对应的公钥证书为:*.pem
如果有不清楚的,请看我之前介绍过的文章

Android自带的可信任的CA公钥证书

还要说明一下,Android系统有自带的安卓认可的证书颁发机构(如:Wosign)颁发的可信任的CA公钥证书,大概有100多个,
可自己查看,各个手机的查看方法可能不一样,在我的手机中,能在下面的位置中找到:
“设置”->”更多设置“->”系统安全“->”信任的凭据”
也就是说,如果你服务器的证书是安卓认可的证书颁发机构颁发的,那么你并不需要在Android端额外安装公钥证书,否则,你就需要安装。
注:在不同版本的Android系统上,可信任的CA证书可能是不一样的,如果你担心在别人的Android系统上可能此CA证书不被信任,那你统一都安装也是没问题的
我在阿里云上申请的免费型DV SSL证书,是属于安卓认可的证书颁发机构颁发的,不需要额外安装,当然我们的自签名证书,是必需要安装的
其实我在测试的过程中,把自签名证书和阿里云上申请的免费型DV SSL证书都用同样的方法安装了,都是OK的

我们下面就开始基于okhttp来安装公钥证书了

先看看我的okhttp和retrofit的gradle版本

compile 'com.squareup.okhttp3:okhttp:3.8.1'
compile 'com.squareup.retrofit2:retrofit:2.3.0'

增加一个OkhttpManager类

统一处理OkHttpClient的证书,完整的代码如下:

import android.content.Context;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Arrays;
import java.util.Collection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.OkHttpClient;

public class OkhttpManager {
    static private OkhttpManager mOkhttpManager=null;
    private InputStream mTrustrCertificate;
    static public OkhttpManager getInstance()
    {
        if(mOkhttpManager==null)
        {
            mOkhttpManager=new OkhttpManager();
        }
        return mOkhttpManager;
    }

    private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
        try {
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            InputStream in = null; // By convention, 'null' creates an empty key store.
            keyStore.load(in, password);
            return keyStore;
        } catch (IOException e) {
            throw new AssertionError(e);
        }
    }

    private X509TrustManager trustManagerForCertificates(InputStream in)
            throws GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }

        // Put the certificates a key store.
        char[] password = "password".toCharArray(); // Any password will work.
        KeyStore keyStore = newEmptyKeyStore(password);
        int index = 0;
        for (Certificate certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificate);
        }

        // Use it to build an X509 trust manager.
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, password);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
        }
        return (X509TrustManager) trustManagers[0];
    }

    public void setTrustrCertificates(InputStream in)
    {
        mTrustrCertificate=in;
    }

    public InputStream getTrustrCertificates()
    {
        return mTrustrCertificate;
    }

    public OkHttpClient build()
    {
        OkHttpClient okHttpClient=null;
        if(getTrustrCertificates()!=null)
        {
            X509TrustManager trustManager;
            SSLSocketFactory sslSocketFactory;
            try {
                trustManager = trustManagerForCertificates(getTrustrCertificates());
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, new TrustManager[] { trustManager }, null);
                sslSocketFactory = sslContext.getSocketFactory();
            } catch (GeneralSecurityException e) {
                throw new RuntimeException(e);
            }
            okHttpClient=new OkHttpClient.Builder()
                    .sslSocketFactory(sslSocketFactory, trustManager)
                    .build();
        }
        else
        {
            okHttpClient=new OkHttpClient.Builder()
                                         .build();
        }
        return okHttpClient;
    }

}

代码解释

代码不少,其实最核心的代码为:

public OkHttpClient build()
{
.......
 trustManager = trustManagerForCertificates(getTrustrCertificates());
 .......
  okHttpClient=new OkHttpClient.Builder()
                    .sslSocketFactory(sslSocketFactory, trustManager)
                    .build();
 ..........
 return okHttpClient;
}

也就是通过

void setTrustrCertificates(InputStream in)

把自己的证书对应的文件set进去

然后通过

trustManager =trustManagerForCertificates(getTrustrCertificates());

okHttpClient=new OkHttpClient.Builder()
                    .sslSocketFactory(sslSocketFactory, trustManager)
                    .build();

就能生成安装好了可信任证书的okHttpClient

OkhttpManager说完了,接下来,就是:

Activity中使用OkhttpManager

1:先把公钥证书文件(如:自签名的mycer.cer或CA证书的:*.pem)放到assets下,
如果使用AndroidStudio的同学,可能没有assets文件夹,自己建此文件夹,如我的为:app\src\main\assets

2:直接贴Activity主要的代码:

public class MyActivity extends AppCompatActivity {
@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       try {
            OkhttpManager.getInstance().setTrustrCertificates(getAssets().open("mycer.cer");
            OkHttpClient mOkhttpClient= OkhttpManager.getInstance().build();
        } catch (IOException e) {
            e.printStackTrace();
        }
}

简单吧,主要代码就那两句,就生成了已安装公钥证书”mycer.cer”的mOkhttpClient
接下来的mOkhttpClient怎样使用,大家都应该清楚了吧,如果不清楚只能看OkHttpClient的基础内容了

好了,OkHttpClient搞掂了

接下来就到Retrofit了

大家应该知到Retrofit默认是以OkHttpClient来作为传输的,既然OkHttpClient搞掂了,那Retrofit就简单了
还是直接贴代码:

 Retrofit retrofit = new Retrofit.Builder()
                .client(mOkhttpClient)
                .baseUrl("your_serverl_url")
                .build();

看,只需在Retrofit中多加一句

.client(mOkhttpClient)

就把已安装了证书的mOkhttpClient作为Retrofit的传输了


更多内容,请关注微信公众号:颜家大少
这里写图片描述

文章评论

写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我是如何打败拖延症的
我是如何打败拖延症的
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
那些争议最大的编程观点
那些争议最大的编程观点
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
 程序员的样子
程序员的样子
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
程序员必看的十大电影
程序员必看的十大电影
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
如何成为一名黑客
如何成为一名黑客
程序员的鄙视链
程序员的鄙视链
程序员都该阅读的书
程序员都该阅读的书
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员应该关注的一些事儿
程序员应该关注的一些事儿
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
代码女神横空出世
代码女神横空出世
10个调试和排错的小建议
10个调试和排错的小建议
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
旅行,写作,编程
旅行,写作,编程
一个程序员的时间管理
一个程序员的时间管理
程序员和编码员之间的区别
程序员和编码员之间的区别
编程语言是女人
编程语言是女人
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
鲜为人知的编程真相
鲜为人知的编程真相
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
我的丈夫是个程序员
我的丈夫是个程序员
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
老程序员的下场
老程序员的下场
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
Java程序员必看电影
Java程序员必看电影
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有