安卓HTTPs的简单兼容


在文章《安卓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网站