Android筆記之證書

           android主要的通信方式是http和https,但是爲了加強安全性,比較建議採用https。

      目前HttpClient建議不要再使用了,因爲在高版本的android系統中逐漸廢棄這種apache的api,轉而採用原生的HttpURLConnection方式

      那麼如何保證https通信安全呢,默認方式下https是信任所有證書的,因此容易受到中間人攻擊,所以需要添加證書校驗這一環節,下面主要介紹添加證書的兩種方式:

     1、自定義證書

           這種方式允許開發人員用自籤的證書來進行https通信,首先是要繼承SSLSocketFactory

public class MySSLSocketFactory extends SSLSocketFactory {


    SSLContext context = SSLContext.getInstance("TLS");


    public UnifiedSSLSocketFactory(KeyStore truststore)
            throws NoSuchAlgorithmException, KeyManagementException,
            KeyStoreException, UnrecoverableKeyException {
        super(truststore);
        MyTrustManager tm = new MyTrustManager(truststore);
        context.init(null, new TrustManager[]{tm}, new SecureRandom());
    }


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


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


}



然後實現X509TrustManager:

public class MyTrustManager implements X509TrustManager {
   
    private X509TrustManager localTrustManager;
    public UnifiedTrustManager(KeyStore localKeyStore) throws KeyStoreException {
        try {          
            this.localTrustManager = createTrustManager(localKeyStore);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    private X509TrustManager createTrustManager(KeyStore store) throws NoSuchAlgorithmException, KeyStoreException {
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init((KeyStore) store);
        TrustManager[] trustManagers = tmf.getTrustManagers();
        return (X509TrustManager) trustManagers[0];
    }
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {        
            localTrustManager.checkServerTrusted(chain, authType);
        
    }
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    @Override
    public X509Certificate[] getAcceptedIssuers() {      
        X509Certificate[] result = localTrustManager.getAcceptedIssuers();            
        return result;
    }
}


其中關於keystore的獲取方式是將自籤的證書放進自定目錄下,然後進行下面的處理:

  
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
   trustStore.load(null, null); 
    ...
   FileInputStream in = new FileInputStream(file);//這裏的file就是你的自簽證書
   CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
    trustStore.setCertificateEntry("ca", certificateFactory.generateCertificate(in)); 

    
經過上面的步驟就能創建你自定義的SSLSocketFactory ,最後一個步驟就是使用這個SSLSocketFactory 了,如下:
HttpsURLConnection con = (HttpURLConnection) requestURL.openConneciton();
con.setSSLSocketFactory(mySSLSocketFactory);




2、上傳證書到系統

      有時候連接只信任系統證書,比如用WebView的時候,因此這時候你需要把你的證書上傳到系統目錄下才有效果,具體方法如下:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
				Intent intent = KeyChain.createInstallIntent();
				Certificate cert = SSLUtil.getCert(context);
				if(null != cert) {					
					try {
						intent.putExtra(KeyChain.EXTRA_CERTIFICATE,cert.getEncoded());
						intent.putExtra(KeyChain.EXTRA_NAME, "ca");
						startActivityForResult(intent, REQUEST_CODE_INSTALL_CERT_TO_SYS);
					} catch (CertificateEncodingException e) {
						e.printStackTrace();
					}
				}
} 



if裏面的判斷是因爲在API低於4.0的android系統是不支持將自定義證書上傳到系統目錄下的,調用這個方法系統會彈出一個對話框讓用戶選擇是否安裝指定證書,用戶同意後才能將證書放到系統目錄,另外並沒有api可以刪除系統證書,只能用戶手動到設置裏面刪除。

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