天天看點

Retrofit2 配置雙向https認證

1 .運維工程師從阿裡雲導出的證書.

伺服器端證書

Retrofit2 配置雙向https認證

用戶端證書

Retrofit2 配置雙向https認證

如果不清楚每種證書是幹什麼用的可以自己查查.https://www.chinassl.net/ssltools/convert-ssl.html

2.轉換證書

伺服器端證書裡我們需要214410367490223.pfx,pfx類型的證書是攜帶私鑰的,我們需要轉換成cer類型把私鑰删除.

我用的是linux系統,windwos安裝openssl可以參考http://blog.csdn.net/leiwuxing/article/details/51692547

Retrofit2 配置雙向https認證

server.cer生成後再把它轉成bks,這裡就需要一個jar包工具bcprov-jdk16-141.jar,參考和下載下傳http://www.itkeyword.com/doc/8039243769809676x164/openssl-c++-ca

Retrofit2 配置雙向https認證
Retrofit2 配置雙向https認證

到這裡伺服器端的證書就轉換完成了.

因為給的用戶端證書裡有我們需要的格式(client.p12),是以就不要轉換了.

3.把server.bks和client.p12放到項目的assets目錄下

4.代碼設定

public class SSL {

    private final static String SERVER_PFX_PASSWORD = "214410367490223";
    private final static String CLIENT_P12_PASSWORD = "koAe5h8F";

    public static SSLSocketFactory getSSLSocketFactory(Context context) {

        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("TLS");
            sslContext.init(getKeyManagerFactory(context).getKeyManagers(), getTrustManagerFactory(context).getTrustManagers(), null);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslContext != null ? sslContext.getSocketFactory() : null;
    }

    /**
     *client端
     * @param context
     * @return
     */
    public static KeyManagerFactory getKeyManagerFactory(Context context){
        KeyStore keyStore = null;
        KeyManagerFactory keyManagerFactory = null;
        try {
            keyStore = KeyStore.getInstance("PKCS12");
            InputStream ksIn = context.getAssets().open("client.p12");
            keyStore.load(ksIn, CLIENT_P12_PASSWORD.toCharArray());
            ksIn.close();
            keyManagerFactory = KeyManagerFactory.getInstance("X509");
            keyManagerFactory.init(keyStore, CLIENT_P12_PASSWORD.toCharArray());
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (UnrecoverableKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return keyManagerFactory;
    }

    /**
     *server端
     * @param context
     * @return
     */
    public static TrustManagerFactory getTrustManagerFactory(Context context){
        KeyStore trustStore = null;
        TrustManagerFactory trustManagerFactory = null;
        try {
            trustStore = KeyStore.getInstance("bks");
            InputStream tsIn = context.getAssets().open("server.bks");
            trustStore.load(tsIn, SERVER_PFX_PASSWORD.toCharArray());
            trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return trustManagerFactory;
    }
}
           
OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .readTimeout(31000, TimeUnit.MILLISECONDS)
                    .connectTimeout(31000, TimeUnit.MILLISECONDS)
                    .addInterceptor(interceptor)//增加這個會導緻CountingRequestBody執行兩次
                    .addInterceptor(new MInterceptor())
                    .cache(cache)
                    .build();
           
這時候請把域名前面改成https.