android之Okhttp连接https添加自产证书

来源:互联网 发布:win10 ssd 磁盘优化 编辑:程序博客网 时间:2024/05/02 04:40

使用Okhttp作为android的网络框架已经流行很久了,如果不需要考虑网络数据安全性问题,仅使用http就已经足够啦。目前项目需要添加支付功能,为了确保数据的安全性,使用https,但是使用的证书不是购买的,是自产的证书。这就产生了问题,怎么样在OKhttp基础上支持https自产证书。

怎么办?查看okhttp说明,是可以向okhttp里添加证书的。下面是向okhttp添加证书的内容了。证书可以浏览器上导出,导时选择X509,导出结果的xxx.cer。

为了方便各模块添加自己的证书,各模块把需要用到的证书都放在assets里和同一路径的目录下(我放置的目录为assets),Android Studio编译时会把所以模块里的assets统一起来,到时遍历这目录就能读取到所有证书了。

这里就需要引入 OkHttpClientManager这个类,代码如下:



import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import cn.ddhl.cust.common.DAppManager;
import cn.ddhl.cust.common.DPrefUtil;
public class OkHttpClientManager {
private static OkHttpClientManager manager;


private OkHttpClientManager() {

}

public static OkHttpClientManager getInstance() {
if (manager == null) {
manager = new OkHttpClientManager();
}
return manager;
}

/**
* 刷新证书
*/
public void updateCertificates() {

//不同环境  处理不同
if (DPrefUtil.getInt(DPrefUtil.KEY_ENV_VALUE, 0) != 0) {
try {

//引入项目里面的自产证书
OkHttpClientManager.getInstance().setCertificates(DAppManager.getContext().getAssets().open("ddhl_ca.crt"));
} catch (Exception e) {
e.printStackTrace();
}
} else {
HttpHandler.getInstance().getClient().setSslSocketFactory(null);
SyncHttpHandler.getInstance().getClient().setSslSocketFactory(null);
}
}


public void setCertificates(InputStream... certificates) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
for (InputStream certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));


try {
if (certificate != null)
certificate.close();
} catch (IOException e) {
}
}

SSL (Secure Socket Layer)为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取及窃听。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。


SSLContext sslContext = SSLContext.getInstance("TLS");


TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory
.getDefaultAlgorithm());


trustManagerFactory.init(keyStore);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
HttpHandler.getInstance().getClient().setSslSocketFactory(sslContext.getSocketFactory());
SyncHttpHandler.getInstance().getClient().setSslSocketFactory(sslContext.getSocketFactory());

不同版本的android系统支持的SSL协议版本不同,所以后台配置的时候需要注意兼容。而且同版本协议中具体的协议内容需要配置一致。
// SSLEngine en = sslContext.createSSLEngine();
// DLog.i("okhttpssl", "支持的协议: " + Arrays.asList(en.getSupportedProtocols()));
// DLog.i("okhttpssl", "启用的协议: " + Arrays.asList(en.getEnabledProtocols()));
// DLog.i("okhttpssl", "支持的加密套件: " + Arrays.asList(en.getSupportedCipherSuites()));
// DLog.i("okhttpssl", "启用的加密套件: " + Arrays.asList(en.getEnabledCipherSuites()));


// ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS).tlsVersions(TlsVersion.TLS_1_2)
// .build();
//
// HttpHandler.getInstance().getClient().setConnectionSpecs(Collections.singletonList(spec));
// SyncHttpHandler.getInstance().getClient().setConnectionSpecs(Collections.singletonList(spec));


} catch (Exception e) {
e.printStackTrace();
}
}
}

注意:需要在项目的application里面刷新证书。如果有不同环境切换的话,也需切换同时刷新证书。





1 0