Android使用okhttp進行自制證書的雙向SSL驗證

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章