Android Https证书认证
Android 开发时,有时对于https的认证需要做处理。使用HttpsURLConnection时,可以指定认证证书。有跳过证书认证(不推荐)和信任指定证书两种做法。先来看跳过证书认证:
跳过证书认证:
1.编写如下几个方法:
/**
* 跳过证书信任
* @param http
* @throws Exception
*/
public void trustAllCertificate(HttpsURLConnection http) throws Exception {
try {
TrustManager[] tm = {new MyX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, tm, new java.security.SecureRandom());
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
http.setHostnameVerifier(new TrustAnyHostnameVerifier());
http.setSSLSocketFactory(sslSocketFactory);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 不进行主机名确认
*/
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
/**
* 信任所有主机 对于任何证书都不做SSL检测
* 安全验证机制,而Android采用的是X509验证
*/
private static class MyX509TrustManager implements X509TrustManager {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
}
2.在打开HttpsUrlConnection后,调用trustAllCertificate(Context context),传入context参数,就可以信任所有主机跳过证书认证。但是不推荐这种做法,本身证书就是为了安全考虑,跳过证书也就相当于背道而驰了,接下来还是看一下指定证书认证的做法:
指定证书认证:
1.指定证书认证需要先拿到证书文件(.cer文件),然后放在src/main/assets目录下,如果没有assets目录,手动创建一个再放进去,如下图:
2.编写如下方法:
/**
* 信任指定证书
*/
public static void trustAppointCertificate(Context inputContext,HttpsURLConnection connection){
SSLContext context = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream in = inputContext.getAssets().open("server.cer");
Certificate ca = cf.generateCertificate(in);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
keystore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keystore);
// Create an SSLContext that uses our TrustManager
context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
connection.setSSLSocketFactory(context.getSocketFactory());
connection.setHostnameVerifier(new TrustAnyHostnameVerifier());
} catch (Exception e){
e.printStackTrace();
}
}
2.其中TrustAnyHostnameVerifier和跳过认证书认证的是同一个类,这里都先不进行主机名的确认。然后还是在打开HttpsURLConnection后,调用这个trustAppointCertificate(Context context,HttpsURLConnection conn)方法,传入上下文和连接对象,就可以信任我们放进去的证书文件了。