Okhttp连接https添加自产证书

使用okhttp作为网络连接时,

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的相关代码:

  // 证书数据
    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就这样了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值