您的位置:首页 > 理论基础 > 计算机网络

okhttp3.2.0适配https,虽然网络上有很多文章。在此借助前人的经验,做一些处理。

2017-01-22 14:34 387 查看
虽然网上ok适配https 的文章一大堆。但是我在用
retrofit2 +Rxjava +Ok 的时候,由于IOS 那边需要适配https,也为了防止资讯页面的网页被运营商劫持。就开始做https 的适配。
发现网络上很多文章,经过一天的实践,发现我的不是请求不到数据,就是闪退,闪退的原因是项目集成了nuwa 热修复。app初始化的时候就请求服务器端的jar。在application类初始化之前请求没有
Content对象没获取到证书,好了 这里 废话不多说,请欣赏核心代码。
private static OkHttpClient myClient;
static SSLSocketFactory sslSocketFactory = null;
static X509TrustManager trustManager;

public static OkHttpClient getOkHttpClient() {
if (myClient == null) {
try {
SSLContext sslContext = trustManagerForCertificates(ttrustedCertificatesInputStream()); //SSLContext.getInstance("TLS");
//            setCard(ttrustedCertificatesInputStream());
sslSocketFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new RuntimeException(e);
} catch (IOException e) {
e.printStackTrace();
}

HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
Interceptor mTokenInterceptor = new Interceptor() {//网络请求拦截器 这里是在所有网络请求的header里加上apikey
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request authorised = originalRequest.newBuilder().addHeader("head", "head").build();
return chain.proceed(authorised);
}
};

myClient = new OkHttpClient.Builder().addInterceptor(interceptor).retryOnConnectionFailure(true).connectTimeout(15, TimeUnit.SECONDS).sslSocketFactory(sslSocketFactory).hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {

return true;
}
}).addNetworkInterceptor(mTokenInterceptor).build();
}
return myClient;
}

public static OkHttpClient getOkHttpClient(Context cc) {
if (myClient == null) {
SSLContext sslContext = null; //SSLContext.getInstance("TLS");
try {
sslContext = trustManagerForCertificates(ttrustedCertificatesInputStream(cc));
sslSocketFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//            setCard(ttrustedCertificatesInputStream(cc));
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
Interceptor mTokenInterceptor = new Interceptor() {//网络请求拦截器 这里是在所有网络请求的header里加上apikey
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request authorised = originalRequest.newBuilder().addHeader("head", "head").build();//这儿的head为了上传头像的时候加的
return chain.proceed(authorised);
}
};
myClient = new OkHttpClient.Builder().retryOnConnectionFailure(true).addInterceptor(interceptor).addNetworkInterceptor(mTokenInterceptor).sslSocketFactory(sslSocketFactory).hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {

return true;
}
}).connectTimeout(15, TimeUnit.SECONDS).build();
}
return myClient;
}

private static InputStream ttrustedCertificatesInputStream(Context cc) {
InputStream inputStream;
//这儿写工厂设计 根据url 打包不同的证书。是为了打包方便
if (Config.APP_URL2.equals("你的线上服url")) {
inputStream = cc.getResources().openRawResource(R.raw.线上服证书);

} else if (Config.APP_URL2.equals("你的线上服url")) {
inputStream = cc.getResources().openRawResource(R.raw.测试服证书);
} else {
inputStream = cc.getResources().openRawResource(R.raw.线上服证书);
}
//这儿是最容易出问题的地方。网上好多地方直接 返回cc.getResources().openRawResource(R.raw.线上服证书)。我直接 这样做请求不到数据,而且只有一个certificate 对象  不知道各位有没有出现。所以在外面套了一个bufferread 来读取
return new BufferedInputStream(inputStream);
//        return new BufferedInputStream(cc.getResources().openRawResource(R.raw.线上服证书));
//        return trustedCertificatesInputStream();
}

private static InputStream ttrustedCertificatesInputStream() {
InputStream inputStream;
if (Config.APP_URL2.equals("线上服url")) {
inputStream = MyApplication.mContext.getResources().openRawResource(R.raw.线上服证书);

} else if (Config.APP_URL2.equals("测试服url")) {
inputStream = MyApplication.mContext.getResources().openRawResource(R.raw.测试服证书);
} else {
inputStream = MyApplication.mContext.getResources().openRawResource(R.raw.线上服证书);
}

return new BufferedInputStream(inputStream);
//        return trustedCertificatesInputStream();
}

private static SSLContext trustManagerForCertificates(InputStream in)
throws GeneralSecurityException, IOException {
//        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
// 这儿也是最容易出问题的,网上的大部分文章缺少后面的参数,。我把后面的 BC去掉,直接异常闪退。不知道各位有没有遇到。
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509", "BC");
Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
if (certificates.isEmpty()) {
throw new IllegalArgumentException("expected non-empty set of trusted certificates");
}

char[] password = CLIENT_KET_PASSWORD.toCharArray(); // Any password will work.
KeyStore keyStore = newEmptyKeyStore(password);
int index = 0;
for (Certificate certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificate);
}
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
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));
}

SSLContext ssContext = SSLContext.getInstance("SSL");
ssContext.init(keyManagerFactory.getKeyManagers(), trustManagers, null);
return ssContext;
}

private static KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = null;
keyStore.load(in, password);
return keyStore;
} catch (IOException e) {
throw new AssertionError(e);
}
}
写两个是 因为 热修复 之前的 引导页需要获取 服务器的热修复jar 包,所以重写了一个方法。。。。谢谢观看。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android
相关文章推荐