关于android使用https单向认证遇到的坑
报错:javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
场景:离线环境中使用服务器端自建的SSL证书,android端使用retrofit实现https请求,实现单向认证。
在网上参考了很多博客,还是没能解决,终于在这一篇博客Https系列之一:https的简单介绍及SSL证书的生成发现了是证书的问题。
服务器的证书是使用JDK自带的Keytool工具生成,制作证书的时候没有写上服务器的IP地址,所以会出现这个错误。
关于如何使用Retrofit实现https单向认证,参考如下:
Https系列之四:https的SSL证书在Android端基于okhttp,Retrofit的使用
最后的最后,对SSLSocketFactoryUtils做了一些小更改:
public class SSLSocketFactoryUtils {
static int keyServerStroreID = R.raw.tomcat_server;
public static SSLSocketFactory createSSLSocketFactory(Context context) {
InputStream trustStream = context.getResources().openRawResource(keyServerStroreID);
SSLSocketFactory mSSLSocketFactory = null;
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{getTurstManager(trustStream)}, new SecureRandom());
mSSLSocketFactory = sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
return mSSLSocketFactory;
}
/**
* 获得指定流中的服务器端证书库
*/
public static X509TrustManager getTurstManager(InputStream certificates) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
Certificate certificate = certificateFactory.generateCertificate(certificates);
keyStore.setCertificateEntry("ca",certificate);
if (certificates!=null){
certificates.close();
}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.
getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
} catch (Exception e) {
Log.e("httpDebug", "SSLSocketFactoryUtils", e);
}
return null;
}
public static void SSLSocketFactoryUtils(Context context) {
try {
InputStream inStream = context.getResources().openRawResource(keyServerStroreID);
// 创建X509工厂类
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// 创建证书对象
X509Certificate oCert = (X509Certificate) cf.generateCertificate(inStream);
inStream.close();
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy/MM/dd");
String info = null;
// 获得证书版本
info = String.valueOf(oCert.getVersion());
Log.e("TAG", "证书版本:" + info);
// 获得证书序列号
info = oCert.getSerialNumber().toString(16);
Log.e("TAG", "证书序列号:" + info);
// 获得证书有效期
Date beforedate = oCert.getNotBefore();
info = dateformat.format(beforedate);
Log.e("TAG", "证书生效日期:" + info);
Date afterdate = oCert.getNotAfter();
info = dateformat.format(afterdate);
Log.e("TAG", "证书失效日期:" + info);
// 获得证书主体信息
info = oCert.getSubjectDN().getName();
Log.e("TAG", "证书拥有者:" + info);
// 获得证书颁发者信息
info = oCert.getIssuerDN().getName();
Log.e("TAG", "证书颁发者:" + info);
// 获得证书签名算法名称
info = oCert.getSigAlgName();
Log.e("TAG", "证书签名算法:" + info);
} catch (CertificateException e) {
e.printStackTrace();
Log.e("TAG", "出错");
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", "出错");
}
}
}