当前位置: 首页 > news >正文

Android 4.4 以下,OkHttp访问Https报错,设置了sslSocketFactory仍无效的解决方法

背景

Android 4.4 及以下,使用 OkHttp 发送 Https 请求,报以下错误:

    javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6b712c90: Failure in SSL library, usually a protocol errorerror:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x68111cd4:0x00000000)at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:448)at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:302)at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:270)at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:162)at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)at okhttp3.RealCall$AsyncCall.execute(RealCall.java:147)at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)at java.lang.Thread.run(Thread.java:841)Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x6b712c90: Failure in SSL library, usually a protocol errorerror:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x68111cd4:0x00000000)at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)... 23 more

一、确保OkHttp的Https配置正确

首先配制好 sslSocketFactory 和 hostnameVerifier:

import android.annotation.SuppressLint
import java.net.InetAddress
import java.net.Socket
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManagerclass MySSLSocketFactory(tm: TrustManager = TrustAllTrustManager()) : SSLSocketFactory() {var internalSSLSocketFactory: SSLSocketFactoryvar context: SSLContext = SSLContext.getInstance("TLSv1.1")init {context.init(null, arrayOf(tm), null)internalSSLSocketFactory = context.socketFactory}override fun getDefaultCipherSuites(): Array<String> {return internalSSLSocketFactory.defaultCipherSuites}override fun createSocket(s: Socket?, host: String?, port: Int, autoClose: Boolean): Socket {val sslSocket = context.socketFactory?.createSocket(s, host, port, autoClose) as SSLSocketsslSocket.enabledProtocols = arrayOf("TLSv1.2", "TLSv1.1")return sslSocket}override fun getSupportedCipherSuites(): Array<String> {return internalSSLSocketFactory.supportedCipherSuites}override fun createSocket(host: String?, port: Int): Socket {val sslSocket = context.socketFactory?.createSocket(host, port) as SSLSocketsslSocket.enabledProtocols = arrayOf("TLSv1.2", "TLSv1.1")return sslSocket}override fun createSocket(host: String?, port: Int, localHost: InetAddress?, localPort: Int): Socket {val sslSocket = context.socketFactory?.createSocket(host, port, localHost, localPort) as SSLSocketsslSocket.enabledProtocols = arrayOf("TLSv1.2", "TLSv1.1")return sslSocket}override fun createSocket(host: InetAddress?, port: Int): Socket {val sslSocket = context.socketFactory?.createSocket(host, port) as SSLSocketsslSocket.enabledProtocols = arrayOf("TLSv1.2", "TLSv1.1")return sslSocket}override fun createSocket(address: InetAddress?, port: Int, localAddress: InetAddress?, localPort: Int): Socket {val sslSocket = context.socketFactory?.createSocket(address, port, localAddress, localPort) as SSLSocketsslSocket.enabledProtocols = arrayOf("TLSv1.2", "TLSv1.1")return sslSocket}@SuppressLint("CustomX509TrustManager", "TrustAllX509TrustManager")class TrustAllTrustManager : X509TrustManager {@Throws(CertificateException::class)override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}@Throws(CertificateException::class)override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}override fun getAcceptedIssuers(): Array<X509Certificate> {return arrayOf()}}
}public class SSLSocketClient {//获取这个SSLSocketFactorypublic static SSLSocketFactory getSSLSocketFactory() {try {SSLContext sslContext = SSLContext.getInstance("SSL");sslContext.init(null, getTrustManager(), new SecureRandom());return sslContext.getSocketFactory();} catch (Exception e) {throw new RuntimeException(e);}}//获取TrustManagerprivate static TrustManager[] getTrustManager() {return new TrustManager[]{new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}}};}//获取HostnameVerifierpublic static HostnameVerifier getHostnameVerifier() {HostnameVerifier hostnameVerifier = new HostnameVerifier() {@Overridepublic boolean verify(String s, SSLSession sslSession) {return true;}};return hostnameVerifier;}
}

在OkHttp中使用:

    val tm = TrustAllTrustManager()val client = OkHttpClient.Builder().sslSocketFactory(MySSLSocketFactory(tm), tm).hostnameVerifier(SSLSocketClient.getHostnameVerifier()).build()val request = Request.Builder().url(url).build()client.newCall(request).enqueue(object : Callback {override fun onFailure(call: Call, e: IOException) {Log.w(TAG, "onFailure: ", e)onResult(Log.getStackTraceString(e))}override fun onResponse(call: Call, response: Response) {val result = response.body()?.string()onResult(result)}})

二、仍然报错的解决方案

如果通过以上的配置,仍然报 Failure in SSL library, usually a protocol error 的错,则有以下两种解决方案:

1. 降级OkHttp

将 OkHttp 降级到 3.9.0,即可正常请求。

2. 配置ConnectionSpec

在 OkHttpClient 创建的过程中,添加 ConnectionSpec 的配置,如下:

    // ConnectionSpec的配置val spec = ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS).tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0).cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA).build()val tm = TrustAllTrustManager()val client = OkHttpClient.Builder().connectionSpecs(Collections.singletonList(spec)).sslSocketFactory(MySSLSocketFactory(tm), tm).hostnameVerifier(SSLSocketClient.getHostnameVerifier()).build()val request = Request.Builder().url(url).build()client.newCall(request).enqueue(object : Callback {override fun onFailure(call: Call, e: IOException) {Log.w(TAG, "onFailure: ", e)onResult(Log.getStackTraceString(e))}override fun onResponse(call: Call, response: Response) {val result = response.body()?.string()onResult(result)}})

相关文章:

Android 4.4 以下,OkHttp访问Https报错,设置了sslSocketFactory仍无效的解决方法

背景 Android 4.4 及以下&#xff0c;使用 OkHttp 发送 Https 请求&#xff0c;报以下错误&#xff1a; javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl0x6b712c90: Failure in SSL library, usually a protocol erro…...

如何扫码查看企业介绍及填写招聘表?招聘二维码在线生成的方法

现在很多企业会通过生成二维码的方式来做企业介绍以及企业招聘&#xff0c;企业信息通过图片、文字、视频及其他内容展示&#xff0c;再创建合适的表单让扫码者按照制定的内容来填写对应的信息&#xff0c;从而完成扫码招聘的目的。 对于也想采用这种方式的小伙伴&#xff0c;…...

如何限制一个账号只在一处登陆

大家好&#xff0c;我是广漂程序员DevinRock&#xff01; 1. 需求分析 前阵子&#xff0c;和问答群里一个前端朋友&#xff0c;随便唠了唠。期间他问了我一个问题&#xff0c;让我印象深刻。 他问的是&#xff0c;限制同一账号只能在一处设备上登录&#xff0c;是如何实现的…...

日常工作总结

日常工作总结 1000. JAVA基础1. 泛型1.1 泛型和Object的区别 1100. Spring1. 常用注解1.1 ControllerAdvice注解1.2 缓存Cacheable 2. 常用方法2.1 BeanUtils.copyProperties的用法 3. 常用功能组件3.1 过滤器Filter 2000. Linux应用 1000. JAVA基础 1. 泛型 1.1 泛型和Objec…...

Android Activity启动模式

文章目录 Android Activity启动模式概述四种启动模式Intent标记二者区别 Android Activity启动模式 概述 Activity 的管理方式是任务栈。栈是先进后出的结构。 四种启动模式 启动模式说明适用场景standard标准模式默认模式&#xff0c;每次启动Activity都会创建一个新的Act…...

【JavaScript】面试手撕防抖

引入 防抖可是前端面试时最频繁考察的知识点了&#xff0c;首先&#xff0c;我们先了解防抖的概念是什么。咳咳。&#x1f440; 防抖&#xff1a; 首先它是常见的性能优化技术&#xff0c;主要用于处理频繁触发的浏览器事件&#xff0c;如窗口大小变化、滚动事件、输入框内容…...

【Kubernetes】K3S

目录 前言一、原理单体架构高可用架构 二、初始化1.配置yum源2.关掉防火墙3.关掉selinux4. 修改内核参数5.关掉swap交换分区 三、安装master节点1. 安装container2.启动master服务 四、安装node节点五、卸载六、总结 前言 各位小伙伴们&#xff0c;大家好&#xff0c;小涛又来…...

Docker实战——容器

目录 Docker 容器的基本概念与操作1.使用“docker create”创建容器。这里基于Nginx的镜像创建了一个容器&#xff0c;名字为mycontainer。2.使用“docker ps -a”命令查看所有的容器&#xff0c;这时的容器不一定是运行状态。3.使用 “docker start” 命令可以启动容器。4.使用…...

亚信安慧AntDB开启超融合数据库新纪元

&#xff08;一&#xff09; 前言 据统计&#xff0c;在信息化时代的今天&#xff0c;人们一天所接触到的信息量&#xff0c;是古人一辈子所能接收到的信息量的总和。当今社会中除了信息量“多”以外&#xff0c;人们对信息处理的“效率”和“速度”的要求也越来越高。譬如&…...

数学建模【多元线性回归模型】

一、多元线性回归模型简介 回归分析是数据分析中最基础也是最重要的分析工具&#xff0c;绝大多数的数据分析问题&#xff0c;都可以使用回归的思想来解决。回归分析的任务就是&#xff0c;通过研究自变量X和因变量Y的相关关系&#xff0c;尝试去解释Y的形成机制&#xff0c;进…...

【 10X summary report】怎么看?详细解读笔记

报告内容 在开始正式的分析之前&#xff0c;需要查看在对齐和计数过程中生成的任何总结统计信息。下图是由Cell Ranger工具创建的10X总结报告&#xff0c;在从10X scRNA-seq实验生成计数矩阵时会生成。 The left half of the report describes sequencing and mapping statist…...

K8S—Pod控制器

目录 1.什么是POD控制器 2.POD控制器有几种类型 3.POD与控制器之间的关系 4.示例 4.1 Deployment 4.2 SatefulSet ①为什么要有headless&#xff1f; ②为什么要有volumeClainTemplate&#xff1f; ③服务发现&#xff1a;就是应用服务之间相互定位的过程。 ④K8S里服…...

LabVIEW石油钻机提升系统数字孪生技术

LabVIEW石油钻机提升系统数字孪生技术 随着数字化、信息化、智能化的发展&#xff0c;石油钻采过程中的石油钻机数字化技术提升成为了提高钻井效率、降低生产成本的重要途径。基于中石油云平台提供的数据&#xff0c;采用数字孪生技术&#xff0c;对石油钻机提升系统进行数字化…...

C#双向链表实现:在当前节点后插入新数据的方法Insert()

目录 1.定义一个泛型节点类并自动属性 2.定义链表类&#xff0c;并实现Append、Print、MoveFirst、 Insert 3.Main方法 1.定义一个泛型节点类并自动属性 /// <summary> /// 定义泛型节点类 /// </summary> /// <typeparam name"T">泛型运算符&…...

10-Java装饰器模式 ( Decorator Pattern )

Java装饰器模式 摘要实现范例 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构 装饰器模式创建了一个装饰类&#xff0c;用来包装原有的类&#xff0c;并在保持类方法签名完整性的前提下&#xff0c;提供…...

Vue.js 实用技巧:深入理解 Vue.set 方法

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…...

单词规律00

题目链接 单词规律 题目描述 注意点 pattern只包含小写英文字母s只包含小写英文字母和 ’ ’s不包含任何前导或尾随对空格s中每个单词都被 单个空格 分隔 解答思路 本题与上一次同构字符串类似&#xff0c;思路可以参照同构字符串 代码 class Solution {public boolean …...

vue3 vite项目一运行就401(Unauthorized)

问题&#xff1a;项目一执行&#xff1a; pnpm run dev, 启动就出错&#xff0c; Failed to load resource: the server responded with a status of 401 (Unauthorized) 分析&#xff1a; 项目之前是正常运行的&#xff0c;没有问题&#xff0c;回溯刚刚改动&#xff0c;还原…...

LeetCode102.二叉树的层序遍历

题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]输入&#xff1a;root [1] 输出&am…...

Java底层自学大纲_JVM篇

JVM专题_自学大纲所属类别学习主题建议课时&#xff08;h&#xff09; A 深入理解Java虚拟机001 JVM类加载器设计原理2.5 A 深入理解Java虚拟机002 基于SPI破解双亲委派机制2.5 A 深入理解Java虚拟机003 JVM内部结构分析2.5 A 深入理解Java虚拟机004 字符串常量池原理2.5 …...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...