美文网首页
基于okHttpClient实现证书绑定

基于okHttpClient实现证书绑定

作者: 机智的黑猫 | 来源:发表于2018-09-12 14:26 被阅读0次

    最近跟华为做合作项目,主要是我这边提供sdk集成到华为的app里,对方要求sdk与我方服务器的数据通信必须使用证书绑定,这里简单记录一下流程。

     //证书的public key 真实key这里就不放出来了, 可以通过 keytool -printcert -rfc -file xxx.crt得到
      private static final String cert = "-----BEGIN CERTIFICATE-----\n" +
                                                             "-----END CERTIFICATE-----";
    
      SSLSocketFactory sslSocketFactory = null;
    
            try {
                InputStream certStream = new Buffer().writeUtf8(certString).inputStream();
                 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");
            }
            char[] password = "".toCharArray(); // Any password will work.
            KeyStore keyStore;
          try {
                keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                InputStream in = null; // By convention, 'null' creates an empty key store.
                keyStore.load(in, password);
            } catch (IOException e) {
                throw new AssertionError(e);
            }
            int index = 0;
            for (Certificate certificate : certificates) {
                String certificateAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(certificateAlias, certificate);
            }
            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));
            }
    
            SSLContext ssContext = SSLContext.getInstance("TLS");
            ssContext.init(keyManagerFactory.getKeyManagers(), trustManagers, null);
             SslSocketFactory   sslSocketFactory = sslContext.getSocketFactory();
            } catch (GeneralSecurityException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                e.printStackTrace();
            }
    OkHttpClient client = new OkHttpClient().newBuilder().sslSocketFactory(sslSocketFactory).hostnameVerifier(STRICT_HOSTNAME_VERIFIER) .build();
    

    主要流程是根据证书创建trustmanager,并以此创建SslSocketFactory对象设置到okhttpclient上,同时要记得配置hostnameVerifier,两者前者负责检验证书,后者负责检验域名。目前测试下来会对所有使用该client的https网络请求做证书验证,如何在同一个client下只筛选特定域名请求暂时不知道如何实现,不过也已经满足功能需求。中间尝试跟了一下证书验证的源码,发现实际实现并不在andorid的jar包里,后续有机会再跟。

    相关文章

      网友评论

          本文标题:基于okHttpClient实现证书绑定

          本文链接:https://www.haomeiwen.com/subject/cgzmgftx.html