Android使用okhttp进行自制证书的双向SSL验证
原创 z879381359 最后发布于2019-06-04 17:16:24 阅读数 569 收藏
展开

   由于互联网全面普及,未来网络安全这块的发展空间很大的。随着物联网的不断应用,人们的生活和网络已经密不可分,网络上承载着数以亿计的各种信息,这些数据信息是个人、企业甚至是国家的战略性资源,所以保障他们的安全是一件非常重要的事情。因此,在未来,各个企业定会在网络安全这块倾尽余力。

   所以为了保障网络安全,最近公司也在做双向验证的https接口,和其它企业进行对接。但是发现网上针对双向验证的资料少之又少,大部分还是单向验证,还有些博客是用绕过验证的方式提交数据,并且有些博客还是错误的。按照其他博客的方法操作不但不能实现,反而还浪费了大量的时间。本文章只针对前端(Android)端的操作进行解读,后台的配置会简略的说明。

    本文章只针对自制证书进行解读。双向SSL主要是看后台的设计,双向验证有两个证书,一个是根证书,一个是客户端证书。根证书由后台生成,客户端证书也可以安排由后台生成。证书的生成可以参考次链接(点击此处)。生成的证书格式为jks。但是android证书类型不支持解析jks文件,我们需要通过转换工具  https://download.csdn.net/download/z879381359/11225612  下载次工具,进行格式转换。

将两个jks转换成bks,然后再把资源放到android的assets目录中

所有工作就已经准备就绪,开始写代码了

补充:代码用的是databinding没有或者不熟悉的话大伙们要改成findviewbyId哦,

导入包:

    implementation "com.squareup.retrofit2:converter-scalars:2.3.0"
    implementation "com.squareup.retrofit2:converter-gson:2.3.0"
    implementation "com.squareup.okhttp3:logging-interceptor:3.8.1"    
 
主类

     
    public class TestActivity extends Activity {
        private TestActivityBinding binding;
     
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            this.binding = DataBindingUtil.setContentView(this, R.layout.test_activity);
            this.binding.setActivity(this);
            this.binding.button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    query();
                }
            });
     
            query();
     
        }
     
        @Override
        protected void onDestroy() {
            super.onDestroy();
        }
     
     
        public void query(){
            String url = "https://192.168.***";
            //创建日志拦截器,用于日志打印
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
     
            OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                    .addInterceptor(interceptor)
                    .sslSocketFactory(SSLHelper.getSSLCertifcation(this), new HttpsUtil.UnSafeTrustManager())
                    .hostnameVerifier(new HttpsUtil.UnSafeHostnameVerifier())//此处设置忽略掉域名校验
                    .build();
            final Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .build();
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    LogUtils.i("请求失败:"+e.getMessage());
                    e.printStackTrace();
                }
     
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    LogUtils.i("请求成功" + response.body().toString());
                    LogUtils.i("请求成功" + response.message());
                }
            });
     
        }
    }

SSLHelper

     
    public class SSLHelper {
        private static final String TAG = "SSLHelper";
        private final static String CLIENT_PRI_KEY = "nk_client.bks";
        private final static String TRUSTSTORE_PUB_KEY = "nk_server.bks";
        private final static String CLIENT_BKS_PASSWORD = "123456";
        private final static String TRUSTSTORE_BKS_PASSWORD = "123456";
        private final static String KEYSTORE_TYPE = "BKS";
        private final static String PROTOCOL_TYPE = "TLS";
        private final static String CERTIFICATE_STANDARD = "X509";
     
        public static SSLSocketFactory getSSLCertifcation(Context context) {
            SSLSocketFactory sslSocketFactory = null;
            try {
                // 服务器端需要验证的客户端证书,其实就是客户端的keystore
                KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
                // 客户端信任的服务器端证书
                KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE);
     
                //读取证书
                InputStream ksIn = context.getAssets().open(CLIENT_PRI_KEY);
                InputStream tsIn = context.getAssets().open(TRUSTSTORE_PUB_KEY);
     
                //加载证书
                keyStore.load(ksIn, CLIENT_BKS_PASSWORD.toCharArray());
                trustStore.load(tsIn, TRUSTSTORE_BKS_PASSWORD.toCharArray());
                ksIn.close();
                tsIn.close();
     
     
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(CERTIFICATE_STANDARD);
                KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CERTIFICATE_STANDARD);
                trustManagerFactory.init(trustStore);
                keyManagerFactory.init(keyStore, CLIENT_BKS_PASSWORD.toCharArray());
     
                //初始化SSLContext
                SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE);
                sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new java.security.SecureRandom());
     
                sslSocketFactory = sslContext.getSocketFactory();
            } catch (KeyStoreException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (CertificateException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (UnrecoverableKeyException e) {
                e.printStackTrace();
            } catch (KeyManagementException e) {
                e.printStackTrace();
            }
            return sslSocketFactory;
        }
    }

HttpsUtil

     
    public class HttpsUtil {
        public static class SSLParams
        {
            public SSLSocketFactory sSLSocketFactory;
            public X509TrustManager trustManager;
        }
     
        public static SSLParams getSslSocketFactory(InputStream[] certificates, InputStream bksFile, String password)
        {
            SSLParams sslParams = new SSLParams();
            try
            {
                TrustManager[] trustManagers = prepareTrustManager(certificates);
                KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
                SSLContext sslContext = SSLContext.getInstance("TLS");
                X509TrustManager trustManager = null;
                if (trustManagers != null)
                {
                    trustManager = new MyTrustManager(chooseTrustManager(trustManagers));
                } else
                {
                    trustManager = new UnSafeTrustManager();
                }
                sslContext.init(keyManagers, new TrustManager[]{trustManager},null);
                sslParams.sSLSocketFactory = sslContext.getSocketFactory();
                sslParams.trustManager = trustManager;
                return sslParams;
            } catch (NoSuchAlgorithmException e)
            {
                throw new AssertionError(e);
            } catch (KeyManagementException e)
            {
                throw new AssertionError(e);
            } catch (KeyStoreException e)
            {
                throw new AssertionError(e);
            }
        }
     
        public static class  UnSafeHostnameVerifier implements HostnameVerifier
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                return true;
            }
        }
     
        public static class UnSafeTrustManager implements X509TrustManager
        {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException
            {
            }
     
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType)
                    throws CertificateException
            {
            }
     
            @Override
            public X509Certificate[] getAcceptedIssuers()
            {
                return new X509Certificate[]{};
            }
        }
     
        private static TrustManager[] prepareTrustManager(InputStream... certificates)
        {
            if (certificates == null || certificates.length <= 0) return null;
            try
            {
     
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(null);
                int index = 0;
                for (InputStream certificate : certificates)
                {
                    String certificateAlias = Integer.toString(index++);
                    keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
                    try
                    {
                        if (certificate != null)
                            certificate.close();
                    } catch (IOException e)
     
                    {
                    }
                }
                TrustManagerFactory trustManagerFactory = null;
     
                trustManagerFactory = TrustManagerFactory.
                        getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(keyStore);
     
                TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
     
                return trustManagers;
            } catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            } catch (CertificateException e)
            {
                e.printStackTrace();
            } catch (KeyStoreException e)
            {
                e.printStackTrace();
            } catch (Exception e)
            {
                e.printStackTrace();
            }
            return null;
     
        }
     
        private static KeyManager[] prepareKeyManager(InputStream bksFile, String password)
        {
            try
            {
                if (bksFile == null || password == null) return null;
     
                KeyStore clientKeyStore = KeyStore.getInstance("BKS");
                clientKeyStore.load(bksFile, password.toCharArray());
                KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                keyManagerFactory.init(clientKeyStore, password.toCharArray());
                return keyManagerFactory.getKeyManagers();
     
            } catch (KeyStoreException e)
            {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            } catch (UnrecoverableKeyException e)
            {
                e.printStackTrace();
            } catch (CertificateException e)
            {
                e.printStackTrace();
            } catch (IOException e)
            {
                e.printStackTrace();
            } catch (Exception e)
            {
                e.printStackTrace();
            }
            return null;
        }
     
        private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers)
        {
            for (TrustManager trustManager : trustManagers)
            {
                if (trustManager instanceof X509TrustManager)
                {
                    return (X509TrustManager) trustManager;
                }
            }
            return null;
        }
     
     
        private static class MyTrustManager implements X509TrustManager
        {
            private X509TrustManager defaultTrustManager;
            private X509TrustManager localTrustManager;
     
            public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException
            {
                TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                var4.init((KeyStore) null);
                defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
                this.localTrustManager = localTrustManager;
            }
     
     
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
            {
     
            }
     
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
            {
                try
                {
                    defaultTrustManager.checkServerTrusted(chain, authType);
                } catch (CertificateException ce)
                {
                    localTrustManager.checkServerTrusted(chain, authType);
                }
            }
     
     
            @Override
            public X509Certificate[] getAcceptedIssuers()
            {
                return new X509Certificate[0];
            }
        }
     
     
    }

Android端的工作就完成啦。文章要是有误,欢迎大家来在下方评论。
————————————————
版权声明:本文为CSDN博主「z879381359」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/z879381359/article/details/90774627

更多相关文章

  1. 通过OTA的方式在局域网分发iOS应用
  2. Android(安卓)Lolipop 屏蔽隐式Intent检查引发的错误
  3. Android使用Https请求服务器,信任所有证书
  4. INSTALL_FAILED_SHARED_USER_INCOMPATIBLE 解决终极办法
  5. Mac上面利用charles抓取https的包(android手机版)
  6. android之AIDL跨进程通信详解 (四)AIDL中RemoteCallbackList的使
  7. Android开发中遇到的几个问题及解决方案
  8. Android手势研究(textview及listview对比验证)(二)
  9. Android(安卓)Studio中如何查看获取MD5和SHA1值(应用签名)

随机推荐

  1. Android(安卓)利用Matrix实现图片随手指
  2. 浅谈Java中Collections.sort对List排序的
  3. mybatisplus的坑 insert标签insert into
  4. 【阿里云镜像】切换阿里巴巴开源镜像站镜
  5. Pycharm安装PyQt5的详细教程
  6. 箭头函数的基础使用
  7. python起点网月票榜字体反爬案例
  8. 类和 Json对象
  9. NPM 和webpack 的基础使用
  10. Python技巧匿名函数、回调函数和高阶函数