Okhttp鏈接https添加自產證書

使用okhttp做爲網絡鏈接時,java

Okhttp現做爲Android網絡鏈接框架已經很流行了,我也使用okhttp有三年了。之前https仍是使用得少的,訪問別人的網站,若是使用了https都是綠色的(在瀏覽器上看,某購火車票網站的不是),在okhttp裏啥問題也沒有,最近的項目是公司本身的服務器使用了https,但證書不是購買的,是本身產生的(使用jdk自產的),okhttp默認拒絕訪問這自產證書的https的鏈接。數組

怎麼辦?查看okhttp說明,是能夠向okhttp裏添加證書的。下面是向okhttp添加證書的內容了。證書能夠瀏覽器上導出,導時選擇X509,導出結果的xxx.cer。瀏覽器

爲了方便各模塊添加本身的證書,各模塊把須要用到的證書都放在assets裏和同一路徑的目錄下(我放置的目錄爲assets/certs),Android Studio編譯時會把因此模塊裏的assets/cert統一塊兒來,到時遍歷這目錄就能讀取到全部證書了。服務器

添加證書,能夠在okhttp訪問網絡前,但我放置在Application.OnCreate裏,目的爲了讓okhttp使用時不用傳入Context,也不用Context滿天飛。網絡

讀取證書文件代碼以下:框架

// 添加https證書
try {
  String[]  certFiles=this.getAssets().list("certs");
  if (certFiles != null) {
    for (String cert:certFiles) {
      InputStream is = getAssets().open("certs/" + cert);
      NetConfig.addCertificate(is); // 這裏將證書讀取出來,,放在配置中byte[]裏
    }
  }
} catch (IOException ioe) {
  ioe.printStackTrace();
}

NetConfig的相關代碼:dom

  // 證書數據
    private static List<byte[]> CERTIFICATES_DATA = new ArrayList<>();
   /**
    * 添加https證書
    * @param inputStream
    */
   public synchronized static void addCertificate(InputStream inputStream) {
       Log.i(TAG,"#addCertificate inputStream = " + inputStream);
       if (inputStream != null) {

           try {
               int ava = 0;// 數據當次可讀長度
               int len = 0;// 數據總長度
               ArrayList<byte[]> data = new ArrayList<>();
               while ((ava = inputStream.available()) > 0) {
                   byte[] buffer = new byte[ava];
                   inputStream.read(buffer);
                   data.add(buffer);
                   len += ava;
               }

               byte[] buff = new byte[len];
               int dstPos = 0;
               for (byte[] bytes:data) {
                   int length = bytes.length;
                   System.arraycopy(bytes, 0, buff, dstPos, length);
                   dstPos += length;
               }

               CERTIFICATES_DATA.add(buff);
           } catch (IOException e) {
               e.printStackTrace();
           }

       }
   }

   /**
  * https證書
  * @return
  */
 public static List<byte[]> getCertificatesData() {
     return CERTIFICATES_DATA;
 }

那麼如今到將證書添加到okhttp裏去了:網站

public OkHttpClient createOkhttp() {

      OkHttpClient.Builder builder = new OkHttpClient.Builder();



       // 添加證書

       List<InputStream> certificates = new ArrayList<>();



       List<String> certs = NetConfig.getCertificates();



       List<byte[]> certs_data = NetConfig.getCertificatesData();

       // 將字節數組轉爲數組輸入流

       if (certs_data != null && !certs_data.isEmpty()) {

           for (byte[] bytes:certs_data) {

               certificates.add(new ByteArrayInputStream(bytes));

           }

       }



       SSLSocketFactory sslSocketFactory = getSocketFactory(certificates);

       if (sslSocketFactory != null) {

           builder.sslSocketFactory(sslSocketFactory);

       }



       return builder.build();



  }



  /**

     * 添加證書

     *

     * @param certificates

     */

    private static SSLSocketFactory getSocketFactory(List<InputStream> certificates) {



        try {

            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

            keyStore.load(null);



            try {

                for (int i = 0, size = certificates.size(); i < size; ) {

                    InputStream certificate = certificates.get(i);

                    String certificateAlias = Integer.toString(i++);

                    keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));



                    if (certificate != null)

                        certificate.close();

                }

            } catch (IOException e) {

                e.printStackTrace();

            }



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



            TrustManagerFactory trustManagerFactory =

                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());



            trustManagerFactory.init(keyStore);

            sslContext.init

                    (

                            null,

                            trustManagerFactory.getTrustManagers(),

                            new SecureRandom()

                    );



            return sslContext.getSocketFactory();



        } catch (Exception e) {

            e.printStackTrace();

        }



        return null;

    }

Ok,https就這樣了。ui

相關文章
相關標籤/搜索