我们在使用https访问服务器的时候都需要校验证书,测试的时候为了方便默认信任的所有的证书,但是在上线的时候就需要设置证书了,一个比较简单的方式就是在客户端内置证书,设置给网络框架,比如OKHttp,这样在网络访问的时候客户端就会校验服务器的证书是不是和本地的证书一致。具体代码如下:
/**
*
* @param inputStream 本地证书的输入流
* @return 创建SSLSocketFactory对象
*/
public static SSLSocketFactory getSocketFactory(InputStream inputStream){
try {
//1:创建CertificateFactory对象
CertificateFactory cf = CertificateFactory.getInstance("X.509");
//2:接收证书输入流,生成证书对象
Certificate ca = cf.generateCertificate(inputStream);
//3:将证书对象放到keyStore中
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", ca);
//4:利用keyStore初始化TrustManagerFactory
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
//5:通过TrustManagerFactory初始化SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, new SecureRandom());
//6:设置给OKhttp,这样OKhttp就会自动校验证书,至于访问的服务器传输过来的证书和本地证书一直才能握手成功,
// 可以通过单例模式在application中初始化
// mOkHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
return sslContext.getSocketFactory();
}catch (Exception e){
e.printStackTrace();
}finally {
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
上面的方法创建了SSLSocketFactory对象,然后设置给OKhttp 即可:
mOkHttpClient.setSslSocketFactory(socketFactory);
设置这种校验证书的逻辑一般放到Application中进行初始化。
因为有时证书会过期,所以我们可以把签发我们夫妻证书的根证书放到apk中来信任,这样如果日后证书替换或者升级,只要还是使用的同一个根证书签发的就不用进行客户端的升级。