android對https的證書驗證(SSL證書)

1. 背景與需求

近期在做IP切換的HTTPS訪問時,遇到了一些問題:客戶端如何進行HTTPS的證書驗證。
其實對於一般的項目基本都是做的單向驗證,即在客戶端證書或者HOST的驗證;對於金融、銀行相關的項目纔會使用的雙向驗證,客戶端與服務端之間都要對彼此進行驗證,以防止中間人進行攻擊。

2.實現目標

本文記錄的是:客戶端實現對HOST的驗證,這樣基本滿足一般項目的需求,也不需要客戶端內置證書,引起更新時候的麻煩。

3. 實現過程

  • 實現SSLSocketFactory ,獲取SSLContext
    我們這裏沒有本地的證書,所以都是生成TrustManager 時都是空實現,如果需要通過內置證書來驗證可以柴查看下面的鏈接。
public class SSLSocketFactoryImp extends SSLSocketFactory {
    private SSLContext sslContext = SSLContext.getInstance("TLS");
    private TrustManager trustManager = null;


    public SSLContext getSSLContext() {
        return sslContext;
    }

    public X509TrustManager getTrustManager() {
        return (X509TrustManager)trustManager;
    }

    public SSLSocketFactoryImp(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException {
        trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                X509Certificate[] x509Certificates = new X509Certificate[0];
                return x509Certificates;
            }
        };

        sslContext.init(null, new TrustManager[]{trustManager}, null);
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return new String[0];
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return new String[0];
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }

    @Override
    public Socket createSocket(Socket socket, String host, int post, boolean autoClose) throws IOException {
        return sslContext.getSocketFactory().createSocket(socket, host, post, autoClose);
    }

    @Override
    public Socket createSocket(String s, int i) throws IOException, UnknownHostException {
        return null;
    }

    @Override
    public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) throws IOException, UnknownHostException {
        return null;
    }

    @Override
    public Socket createSocket(InetAddress inetAddress, int i) throws IOException {
        return null;
    }

    @Override
    public Socket createSocket(InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) throws IOException {
        return null;
    }
}
  • 關鍵步驟:驗證HOST
    這裏是基於OKHTTP來進行的驗證操作,主要依靠:HttpsURLConnection.getDefaultHostnameVerifier().verify("你的域名", session)方法來驗證域名是否一致
KeyStore trustStore;
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
SSLSocketFactoryImp ssl = new SSLSocketFactoryImp(KeyStore.getInstance(KeyStore.getDefaultType()));

            HostnameVerifier hostnameVerifier = new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    boolean verify = HttpsURLConnection.getDefaultHostnameVerifier().verify("你的域名", session);
                    return verify;
                }
            };

builder.sslSocketFactory(ssl.getSSLContext().getSocketFactory(), ssl.getTrustManager()).hostnameVerifier
                    (hostnameVerifier);

4.一定要閱讀的文章

上面只是簡單的記錄驗證HOST的方式,下面的文章會讓你收穫更多。
1. 阿里移動安全:Android安全開發之安全使用HTTPS

2. 淺析HTTPS中間人攻擊與證書校驗

3. Android官方培訓課程 : 使用HTTPS與SSL


鏈接:https://www.jianshu.com/p/d7e247749071
 

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