okhttp系列之https

1. 什么是https

https,也叫做http over TLS,TLS的前身是SSL。https与http的区别在于https在http与tcp之间加了一层安全层,https会对通信双方进行身份校验和数据加密,保证了传输的安全性。

2. 证书

凡是https的网站都需要一张证书
证书可以是权威机构CA颁发的,也可以是自签名的证书
证书一般有好几层,最顶层就是CA的根证书,这也很好理解,全世界那么多https网站,如果不分层的话,客户端无法保证内置全部的证书,证书群体就像一个树型结构,它们的子证书不一样,但根证书就那么一个或者几个。
客户端一般会内置CA的根证书,因此CA颁发的证书会被校验通过,而自签名的证书就需要在客户端内置了。

证书包含了很多信息,如颁发机构,有效期,不过其中最重要的就是公钥和私钥了,其中公钥是公开的,私钥是保存在服务端的。

3. https的通信过程

https通信过程.jpg

第一步:校验证书
客户端发起一个https的请求,服务端会返回一个证书链给客户端(公钥可以在证书中看到),由于客户端内置了CA根证书,如何该证书是CA颁发或者CA的二级证书结构颁发的,就会校验通过,如果是自签名的证书,则需要将证书导入到客户端。
当然如果证书过期了,也不会校验通过。
这里我其实有一个疑问,如果拦截方的证书也是CA颁发的,会怎么样?

第二步:生成对称秘钥
客户端随机生成一个key值,该key值就是对称秘钥,利用证书中的公钥对对称秘钥加密,然后发送给服务端,服务端利用证书中的私钥解密,拿到对称秘钥,这个过程就是用到了非对称加密

第三步:对通信内容进行加密
通过对称秘钥对请求进行加密,发送给服务端,服务端利用对称秘钥解密,并对响应内容进行加密,客户端也同样能解密,这个过程就是对称加密

至此就是https得安全传输过程

4. OkHttp中https的应用

由于CA颁发的证书,手机里面已经预置了,这里只需要对添加对自签名证书的校验即可

public class Https1Utils {

  private InputStream[] certificates;
  private InputStream bksFile;
  private String password;


public SSLSocketFactory sslSocketFactory;
public X509TrustManager trustManager;
public Https1Utils(InputStream[] certificates, InputStream bksFile, String password) {
    this.certificates = certificates;
    this.bksFile = bksFile;
    this.password = password;

    initSSL();
}

private void initSSL() {
    getSslSocketFactory();
}

private SSLSocketFactory getSslSocketFactory() {
    try {
        trustManager = getTrustManager();
        KeyManager[] keyManagers = prepareKeyManager();
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagers, new TrustManager[]{trustManager}, null);
        sslSocketFactory = sslContext.getSocketFactory();
        return sslSocketFactory;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
    return null;
}


private X509TrustManager getTrustManager() {
    if (certificates == null || certificates.length <= 0)
        return null;
    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)

            {
            }
        }
        TrustManagerFactory trustManagerFactory = null;

        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));
        }
        X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
        return trustManager;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

private KeyManager[] prepareKeyManager() {
    try {
        if (bksFile == null || password == null)
            return null;

        KeyStore clientKeyStore = KeyStore.getInstance("BKS");
        clientKeyStore.load(bksFile, password.toCharArray());
        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(clientKeyStore, password.toCharArray());
        return keyManagerFactory.getKeyManagers();

    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
  }

}

 if (HttpConfig.certificates != null) {
        Https1Utils https1Utils=new Https1Utils(HttpConfig.certificates, null, null);
      builder.sslSocketFactory(https1Utils.sslSocketFactory,https1Utils.trustManager);   
 }

只需要在Application中将证书流设置进来即可

NetWorkUtil.getInstance().setCertificates(getAssets.open(xxx.cer));

//如果服务端给的是字符串,可以做如下转换

NetWorkUtil.getInstance().setCertificates(new Buffer()
                    .writeUtf8(CER_12306)
                    .inputStream());
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351

推荐阅读更多精彩内容