在文章
《安卓RXJAVA+Retrofit 网络请求》中贴过一段HttpUtils工具类。后来遇到Https的需求,就要对其进行改造。改造设计到3个内容SSLSocketFactory,X509TrustManager,HostnameVerifier
SSLSocketFactory其实是一个https请求连接管理类,X509TrustManager是https证书的校验类,HostnameVerifier是https请求对域名的校验类。
在简单兼容中,程序会忽视https证书和域名校验,适用于不需要校验的场景。
SslContextFactory
public class SslContextFactory {
private static final String CLIENT_TRUST_PASSWORD = "xxxxxx";//信任证书密码
private static final String CLIENT_AGREEMENT = "TLS";//使用协议
private static final String CLIENT_TRUST_MANAGER = "X509";
private static final String CLIENT_TRUST_KEYSTORE = "BKS";
SSLContext sslContext = null;
public SSLContext getSslSocket(Context context) {
try {
//取得SSL的SSLContext实例
sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
//取得TrustManagerFactory的X509密钥管理器实例
TrustManagerFactory trustManager = TrustManagerFactory.getInstance(CLIENT_TRUST_MANAGER);
//取得BKS密库实例
KeyStore tks = KeyStore.getInstance(CLIENT_TRUST_KEYSTORE);
InputStream is = context.getResources().openRawResource(R.raw.ssl);
try {
tks.load(is, CLIENT_TRUST_PASSWORD.toCharArray());
} finally {
is.close();
}
//初始化密钥管理器
trustManager.init(tks);
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
}};
//初始化SSLContext
//sslContext.init(null, trustManager.getTrustManagers(), null);
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (Exception e) {
Log.e("SslContextFactory", e.getMessage());
}
return sslContext;
}
}
X509TrustManager
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing,接受任意客户端证书
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing,接受任意服务端证书
}
public X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
};
HostnameVerifier
HostnameVerifier hnv = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
// Always return true,接受任意域名服务器
return true;
}
};
调用时先在getRetrofit中
SSLSocketFactory sslSocketFactory = new SslContextFactory().getSslSocket(context).getSocketFactory();
然后在mClient中加入 sslSocketFactory 和 hostnameVerifier 就OK了
OkHttpClient mClient = new OkHttpClient.Builder()
.addInterceptor(mInterceptor)//应用程序拦截器
.addNetworkInterceptor(mNetInterceptor)//网络拦截器
.sslSocketFactory(sslSocketFactory,tm)
.hostnameVerifier(hnv)
.cache(mCache)//添加缓存
.build();
在HttpURLConnection中调用首先将HttpURLConnection改成HttpsURLConnection然后添加
conn.setSSLSocketFactory(sslSocketFactory);
conn.setHostnameVerifier(hnv);
即可顺利访问https网站