#okhttp访问https数据
公司处于安全的考虑,项目中都采用了https加密协议进行数据传输,好多都是采用的自签名的证书,这种情况下用okhttp访问接口就会报错
##https的工作原理:
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。握手过程的简单描述如下:
- 浏览器将自己支持的一套加密算法、HASH算法发送给网站。
- 网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
- 浏览器获得网站证书之后,开始验证证书的合法性,如果证书信任,则生成一串随机数字作为通讯过程中对称加密的秘钥。然后取出证书中的公钥,将这串数字以及HASH的结果进行加密,然后发给网站。
- 网站接收浏览器发来的数据之后,通过私钥进行解密,然后HASH校验,如果一致,则使用浏览器发来的数字串使加密一段握手消息发给浏览器。
- 浏览器解密,并HASH校验,没有问题,则握手结束。接下来的传输过程将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
握手过程中如果有任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。
##okhttp访问自签名的https数据服务器
-
将服务器端的.cer后缀结尾的证书放到assets目录下
-
添加https的工具类进行认证
import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.util.Arrays; import java.util.Collection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import okhttp3.OkHttpClient; public final class HTTPSUtils { private OkHttpClient client; public Context mContext; /** * 获取OkHttpClient实例 * [@return](https://my.oschina.net/u/556800) */ public OkHttpClient getInstance() { return client; } /** * 初始化HTTPS,添加信任证书 * [@param](https://my.oschina.net/u/2303379) context */ public HTTPSUtils(Context context) { mContext = context; X509TrustManager trustManager; SSLSocketFactory sslSocketFactory; final InputStream inputStream; try { inputStream = mContext.getAssets().open("srca.cer"); // 得到证书的输入流 try { trustManager = trustManagerForCertificates(inputStream);//以流的方式读入证书 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{trustManager}, null); sslSocketFactory = sslContext.getSocketFactory(); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } client = new OkHttpClient.Builder() .sslSocketFactory(sslSocketFactory, trustManager) .build(); } catch (IOException e) { e.printStackTrace(); } } /** * 以流的方式添加信任证书 */ private X509TrustManager trustManagerForCertificates(InputStream in) throws GeneralSecurityException { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in); if (certificates.isEmpty()) { throw new IllegalArgumentException("expected non-empty set of trusted certificates"); } // Put the certificates a key store. char[] password = "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); } // Use it to build an X509 trust manager. 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)); } return (X509TrustManager) trustManagers[0]; } /** * 添加password * [@param](https://my.oschina.net/u/2303379) password * [@return](https://my.oschina.net/u/556800) * [@throws](https://my.oschina.net/throws) GeneralSecurityException */ private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException { try { KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); // 这里添加自定义的密码,默认 InputStream in = null; // By convention, 'null' creates an empty key store. keyStore.load(in, password); return keyStore; } catch (IOException e) { throw new AssertionError(e); } }
}
####代码中请求
public void getResult(Context context ,String url) {
Request request = new Request.Builder()
.url(url)
.build();
HTTPSUtils httpsUtils = new HTTPSUtils(context);
httpsUtils.getInstance().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("--------------onFailure--------------" + e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println("--------------onResponse--------------" + response.body().string());
}
});
}
【总监】十二春秋之,3483099@qq.com; 【Master】zelo,616701261@qq.com;【运营】狼行天下,897221533@qq.com; 【产品设计】流浪猫,364994559@qq.com;【体验设计】兜兜,2435632247@qq.com; 【iOS】淘码小工,492395860@qq.com;iMcG33K,imcg33k@gmail.com;【Android】人猿居士,1059604515@qq.com;思路的顿悟,1217022114@qq.com; 【java】首席工程师MR_W,feixue300@qq.com;【测试】土镜问道,847071279@qq.com; 【数据】喜乐多,42151960@qq.com;【安全】保密,你懂的。