记录使用OkHttp库时候遇到的一些小问题
1.ssl验证时出现的相关错误
当我们使用https来进行数据传输加密,身份校验的时候,HTTP 和 TCP 之间额外加了一层 SSL/TLS来做这部分工作(确定支持的TLS协议版本,建立连接并交互证书,验证其有效性,最后通过非对称加密的方式和服务器返回的证书公钥生成一个零时的秘钥用作后续通信时的对称加解密通信数据)。
SSL/TLS具体工作原理可查看此文
可能遇到的相关错误:
1.Unable to resolve host "xxx.xxxxxx.com": No address associated with hostname
2.HTTP FAILED: javax.net.ssl.SSLHandshakeException: Connection closed by peer
如果后台记录到类似日志,大多数情况下可通过上下文相关辅助日志分析:
1.用户自身网络状态是否良好,ip,country等信息也可以帮助分析
2.用户是否开启了vpn,是否使用了第三方代理抓包工具 ,通过其uuid追踪他的操作日志,查询是否为可疑用户
3.用户手机的型号与版本,已知部分低版本手机/某些特殊的三星手机,并不默认支持TLS协议,此时需要额外设置okhttpclient或相关容错处理okhttp-issue
4.server端支持的TLS协议版本是否过老或者过新?
个人认为大多数情况都是因为前两条原因导致的此问题,处理方式也可以仁者见仁智者见智:
1.做好网络状态判断后,告知用户retry即可
2.通过设置自定义sslSocketFactory和hostnameVerifier信任所有请求的验证SO上的解决方案
public final class NetworkHelper implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public static SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssfFactory = null;
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{new NetworkHelper()}, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception e) {
}
return ssfFactory;
}
public static class TrustAllHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
}
2.使用okhttp时候,如果手动去设置accept-encoding为gzip/br/deflate等压缩方式时,其内部自动解压缩的逻辑会失效
类似于if (userSettedAcceptEncoding) return else doInternalUncompress,导致返回的response.body()为压缩过后的无意义二进制流。此时的解决方案:
1.去除accept-encoding header即可
2.自己写解压缩的Interceptor逻辑,但是非常不推荐此方法,自己有遇到有时work有时不work的情况,未深究。