美文网首页工作生活
Android okhttp3.0配置https的自签证书和信任

Android okhttp3.0配置https的自签证书和信任

作者: 晓涵说 | 来源:发表于2019-07-02 07:07 被阅读0次

    1.Https相关知识

    1.1 http与https的区别

    HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

    HTTPS和HTTP的区别主要如下:

    • https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
    • http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
    • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
    • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

    1.2 Https的优点

    • 认证用户和服务器,确保数据发送到正确的客户机和服务器;(验证证书)
    • 加密数据以防止数据中途被窃取;(加密)
    • 维护数据的完整性,确保数据在传输过程中不被改变。(摘要算法)

    2.Okhttp中使用自签名证书

    一般支持https的网站,都是CA(Certificate Authority)机构颁发的证书,但是一般该机构颁发的证书需要提供费用且有使用时间的限制,到期需要续费。否则默认该链接是不信任的,通过okHttp无法直接访问。

    但是我们可以使用自签的方式,通过JDK自带的keytool.exe 生成一个自己的证书,然后使用该证书内容。虽然也是会出现提示“不安全”,但是我们可以通过okhttp访问链接。

    2.1 使用自签证书

    将证书文件放置在assets目录(也可以放置在其他目录下,只要能正确读取到该文件),在创建OkhttpClient对象时sslSocketFactory()将该证书信息添加。

    private SSLContext getSLLContext() {
            SSLContext sslContext = null;
            try {
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                InputStream certificate = mContext.getAssets().open("gdroot-g2.crt");
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(null);
                String certificateAlias = Integer.toString(0);
                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
                sslContext = SSLContext.getInstance("TLS");
                final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(keyStore);
                sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
            } catch (CertificateException e) {
                e.printStackTrace();
            } catch (KeyStoreException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }
            return sslContext;
        }
    

    通过以上代码可以看出,通过InputStream方式读取证书信息,因此为了避免将证书文件打包到APK中,我们可以直接将证书文件内容放置在String中,将该字符串转为流的形式。

    在使用okhttp时,将其设置到sslSocketFactory中。

    OkHttpClient httpClient = new OkHttpClient().newBuilder()
                    .sslSocketFactory(getSLLContext().getSocketFactory())
                    .build();
    

    2.2 信任所有证书

    通过添加证书的形式,可以实现客户端访问Https服务端的功能,但是如果服务端更换证书内容,那么客户端需要相应的更换https证书,否则无法正常交互获取不到数据,我们可以通过自定义X509TrustManager的形式实现来规避所有的证书检测,实现信任所有证书的目的。

     private OkHttpClient getHttpsClient() {
            OkHttpClient.Builder okhttpClient = new OkHttpClient().newBuilder();
            //信任所有服务器地址
            okhttpClient.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String s, SSLSession sslSession) {
                    //设置为true
                    return true;
                }
            });
            //创建管理器
            TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
                @Override
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] x509Certificates,
                        String s) throws java.security.cert.CertificateException {
                }
    
                @Override
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] x509Certificates,
                        String s) throws java.security.cert.CertificateException {
                }
    
                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[] {};
                }
            } };
            try {
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    
                //为OkHttpClient设置sslSocketFactory
                okhttpClient.sslSocketFactory(sslContext.getSocketFactory());
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return okhttpClient.build();
        }
    

    创建X509TrustManager对象,并实现其中的方法,由于X509TrustManager是通用证书格式,只需要拿到该格式就行。最后init该安全协议,将其放入okhttp的sslSocketFactory中。
    由于Retrofit只是对Okhttp网络接口的封装,因此实际使用中,该方法同样适用于Retrofit中。

    欢迎关注晓涵说(CSDN)xukang868(github)账号信息,查看更多文章。

    相关文章

      网友评论

        本文标题:Android okhttp3.0配置https的自签证书和信任

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