基于okHttpClient實(shí)現(xiàn)證書綁定

最近跟華為做合作項(xiàng)目,主要是我這邊提供sdk集成到華為的app里,對(duì)方要求sdk與我方服務(wù)器的數(shù)據(jù)通信必須使用證書綁定,這里簡(jiǎn)單記錄一下流程。

 //證書的public key 真實(shí)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();

主要流程是根據(jù)證書創(chuàng)建trustmanager,并以此創(chuàng)建SslSocketFactory對(duì)象設(shè)置到okhttpclient上,同時(shí)要記得配置hostnameVerifier,兩者前者負(fù)責(zé)檢驗(yàn)證書,后者負(fù)責(zé)檢驗(yàn)域名。目前測(cè)試下來會(huì)對(duì)所有使用該client的https網(wǎng)絡(luò)請(qǐng)求做證書驗(yàn)證,如何在同一個(gè)client下只篩選特定域名請(qǐng)求暫時(shí)不知道如何實(shí)現(xiàn),不過也已經(jīng)滿足功能需求。中間嘗試跟了一下證書驗(yàn)證的源碼,發(fā)現(xiàn)實(shí)際實(shí)現(xiàn)并不在andorid的jar包里,后續(xù)有機(jī)會(huì)再跟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容