使用Retrofit 2时遭遇SSLException异常求助
这种突然出现的SSL连接失败确实挺闹心的,尤其是昨天还正常运行的功能今天突然挂了。结合你提到的后端已启用TLS1.2、排查过Android 4.x相关方案但无效的情况,我给你几个针对性的排查和解决思路:
优先排查后端/中间层的临时变更
既然功能昨日正常,大概率是后端或CDN、负载均衡这类中间服务的配置发生了临时调整:- 检查证书状态:有没有证书过期、更新,或者证书链不完整?可以用
curl -v --tlsv1.2 https://你的接口域名命令测试,看返回的证书信息里是否有验证错误提示。 - 确认加密套件兼容性:Android 4.x对TLS1.2的支持有限,很多高安全级别的加密套件(比如ECDHE-RSA-AES256-GCM-SHA384)无法识别。如果后端最近调整了加密套件的优先级,可能导致握手失败触发连接关闭。
- 检查证书状态:有没有证书过期、更新,或者证书链不完整?可以用
确保OkHttpClient正确启用TLS1.2(针对Android 4.x)
Android 4.1-4.4系统默认不启用TLS1.2,即使后端支持,也需要手动配置OkHttpClient来强制开启:// 构建支持TLS1.2的OkHttpClient OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(createTls12SocketFactory(), getTrustManager()) .connectionSpecs(Arrays.asList( ConnectionSpec.MODERN_TLS, // 包含TLS1.2 ConnectionSpec.COMPATIBLE_TLS // 兼容旧版本TLS )) .build(); // 自定义TLS1.2 SocketFactory private SSLSocketFactory createTls12SocketFactory() { try { SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, new TrustManager[]{getTrustManager()}, new SecureRandom()); return sslContext.getSocketFactory(); } catch (Exception e) { throw new RuntimeException(e); } } // 获取信任管理器(生产环境请替换为信任指定证书的实现,不要用TrustAll) private X509TrustManager getTrustManager() { return new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted(X509Certificate[] chain, String authType) {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; }注意:生产环境不要使用上述
TrustAll的信任管理器,要配置信任后端的合法证书,避免安全风险。排查证书链完整性
很多时候后端只部署了服务器证书,缺少中间证书,而Android 4.x的系统信任库无法自动补全中间证书,导致握手失败。可以用在线SSL检测工具检查你的域名,确认证书链是否完整,如果有缺失,让后端补全中间证书文件。排除网络环境干扰
测试设备如果使用了代理、VPN或者处于特殊网络环境(比如公司内网),可能会干扰SSL握手过程。建议关闭代理/VPN,切换到普通移动网络或家用WiFi重试,看问题是否消失。抓包定位握手细节
用Charles或Wireshark抓包分析SSL握手流程:- 查看
Client Hello消息是否包含TLS1.2版本; - 查看
Server Hello是否返回TLS1.2,有没有出现handshake failure这类Alert消息;
通过抓包可以精准定位是客户端配置问题、后端响应问题还是加密套件不兼容导致的连接关闭。
- 查看
验证多设备兼容性
如果只有Android 4.x设备出现问题,那核心还是TLS兼容性问题;如果Android 5+或其他平台也出现同样错误,那可能是后端服务器过载、防火墙拦截请求等其他问题,需要联系后端团队排查服务器状态。
内容的提问来源于stack exchange,提问作者Hayk Mkrtchyan

