Okhttp连接https添加自产证书

来源:互联网 发布:什么叫开车 网络用词 编辑:程序博客网 时间:2024/05/01 21:54

使用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就这样了。

原创粉丝点击