Android – OkHttp 访问 https 的怪问题

💡 原文中文,约8700字,阅读约需21分钟。
📝

内容提要

最近使用OkHttp访问https请求时遇到了一些问题,经过实践发现是由于https证书协议不匹配导致的。在装备OkHttp时,需要注意服务端支持的ssl协议,并相应地配置SSLSocketFactory和HostnameVerifier。在Android设备上可能会出现一些问题,如协议错误和类型转换异常,需要根据具体情况进行处理。建议使用TLSv1.2作为最低支持标准,并根据服务端证书进行配置。

🔎

延伸解读

协议选择:TLS 1.2 是当前基准

文章指出,OkHttp 从 2014 年起不再支持 SSLv3,2019 年起不再支持 TLSv1 和 TLSv1.1,以 TLSv1.2 为最低标准。服务端证书可能支持不同协议,但主流网站均支持 TLSv1.2。因此,配置 OkHttp 时应优先使用 TLS 协议,并确保服务端支持 TLSv1.2,否则需考虑降级 OkHttp 版本或调整服务端配置。

Android 版本差异:旧设备需强制启用 TLSv1.2

Android 4.1 开始支持 TLSv1.2,但直到 Android 5.0 才默认启用。在 Android 4.x 设备上,即使 OkHttp 配置了 TLS,也可能因系统未启用 TLSv1.2 而导致握手失败。此时需自定义 SSLSocketFactory,在创建 Socket 后强制设置启用协议为 TLSv1.2,以解决兼容性问题。

异常处理:类型转换错误的特殊案例

极个别 Android 4.x 设备上,OkHttp 调用 getEnabledProtocols() 时可能抛出 ClassCastException,提示 int[] 无法转换为 String[]。这可能是 ROM 修改所致。文章通过自定义 DelegateSSLSocket 并重写 setEnabledProtocols() 方法绕过该问题,但此方案仅适用于 Android 5.0 以下,高版本使用可能导致崩溃。

配置要点:SSLSocketFactory 与 HostnameVerifier

OkHttp 默认配置足以访问一般 HTTPS 请求,但遇到私有证书、过期证书或客户端未启用协议时需手动配置。需设置 SSLSocketFactory 指定协议,并配置 HostnameVerifier 校验主机名。注意在 Android 10 及以上,sslSocketFactory 方法必须传入 X509TrustManager,否则会闪退。

❓

Q&A

使用OkHttp访问HTTPS时常见的问题有哪些?

常见问题包括SSL握手失败和类型转换异常,通常与协议不匹配或设备支持的TLS版本有关。

如何配置OkHttp以支持TLSv1.2?

需要自定义SSLSocketFactory并强制启用TLSv1.2,确保在创建Socket时设置相应的协议。

为什么在Android 4.x设备上可能无法使用TLSv1.2?

因为TLSv1.2在Android 4.x设备上默认未启用,需要手动强制启用才能解决问题。

OkHttp支持哪些HTTPS证书协议?

OkHttp支持的HTTPS证书协议包括SSLv3、TLSv1、TLSv1.1、TLSv1.2和TLSv1.3,但自2014年起不再支持SSLv3。

如何处理SSL握手失败的问题?

首先检查客户端使用的证书协议与服务端支持的协议是否一致,必要时调整OkHttp的SSLSocketFactory配置。

在使用OkHttp时,如何配置HostnameVerifier?

可以通过OkHttpClient.Builder中的hostnameVerifier方法来配置HostnameVerifier,以确保主机名一致性。

🏷️

标签

➡️

继续阅读