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));
HttpsURLConnection con = (HttpURLConnection) requestURL.openConneciton();
con.setSSLSocketFactory(mySSLSocketFactory);
2、上傳證書到系統
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();
}
}
}