https Android 5.0 以下TLS 版本过低造成的问题
异常如下
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x610df808: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x410f976a:0x00000000)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:412)
at okhttp3.internal.connection.RealConnection.connectTls(Paramount:281)
at okhttp3.internal.connection.RealConnection.establishProtocol(Paramount:251)
at okhttp3.internal.connection.RealConnection.connect(Paramount:151)
at okhttp3.internal.connection.StreamAllocation.findConnection(Paramount:192)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(Paramount:121)
at okhttp3.internal.connection.StreamAllocation.newStream(Paramount:100)
at okhttp3.internal.connection.ConnectInterceptor.intercept(Paramount:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(Paramount:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(Paramount:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(Paramount:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(Paramount:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(Paramount:185)
at okhttp3.RealCall.execute(Paramount:69)
at com.qihoo.mm.paramount.tools.glide.j.b(Paramount:44)
at com.qihoo.mm.paramount.tools.glide.j.a(Paramount:21)
at com.bumptech.glide.load.b.f$a.b(Paramount:70)
at com.bumptech.glide.load.b.f$a.a(Paramount:53)
at com.bumptech.glide.load.engine.a.e(Paramount:170)
at com.bumptech.glide.load.engine.a.c(Paramount:128)
at com.bumptech.glide.load.engine.h.f(Paramount:122)
at com.bumptech.glide.load.engine.h.d(Paramount:101)
at com.bumptech.glide.load.engine.h.run(Paramount:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$a$1.run(Paramount:118)
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x610df808: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x410f976a:0x00000000)
at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371)
... 35 more
由于集成的 SSL 库版本不同,不同 Android 版本的默认 SSL/TLS 版本配置如下表:
| Protocol | Supported (API Levels) | Enabled by default (API Levels) |
|---|---|---|
| SSLv3 | 1–TBD | 1–22 |
| TLSv1 | 1+ | 1+ |
| TLSv1.1 | 20+ | 20+ |
| TLSv1.2 | 20+ | 20+ |
在 Android 5.0 之前,最高支持的 SSL/TLS 版本为 TLSv1,而这个版本实际上是一个安全性并不是太好的版本,当前已经有许多网站配置为不再支持这种老版本的 SSL/TLS 。在用 Android 5.0 之前的设备,访问一些不再支持 TLSv1 及之前 SSL/TLS 版本的网站的时候,就会出现一些问题。
在 Android 4.3、Android 4.2.2 和 Android 4.1.1 上,用相同版本的 OkHttp 访问前面配置为最低支持 TLSv1.1 的 HTTP 服务器时,抛出了完全相同的异常。
客户端版本低于服务器支持的最低 SSL/TLS 版本时,HTTPS 连接会在握手阶段失败。
为请求的网络客户端设置一个特殊的SSLSocketFactory
import android.os.Build
import android.util.Log
import com.android.core.Arrays
import com.qihoo.mm.paramount.env.AppEnv
import okhttp3.OkHttpClient
import java.io.IOException
import java.net.InetAddress
import java.net.Socket
import java.net.UnknownHostException
import java.security.GeneralSecurityException
import java.security.KeyStore
import javax.net.ssl.*
public class Tls12SocketFactory extends SSLSocketFactory {
private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"}; final SSLSocketFactory delegate; public Tls12SocketFactory(SSLSocketFactory base) {
this.delegate = base;
} @Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
} @Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
} @Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return patch(delegate.createSocket(s, host, port, autoClose));
} @Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return patch(delegate.createSocket(host, port));
} @Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return patch(delegate.createSocket(host, port, localHost, localPort));
} @Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return patch(delegate.createSocket(host, port));
} @Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return patch(delegate.createSocket(address, port, localAddress, localPort));
} private Socket patch(Socket s) {
if (s instanceof SSLSocket) {
((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
}
return s;
}
}
修改默认X509TrustManager
private X509TrustManager getDefaultTrustManager() {
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
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];
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.
}
}
设置OkHttpClient
private OkHttpClient initOkHttpClient() {
OkHttpClient builder = OkHttpClient.Builder()
try {
if(DEBUG){
Log.i(TAG,"initOkHttpClient")
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Tls12SocketFactory.enableTls12OnPreLollipop(builder)
}
builder.readTimeout(10L, TimeUnit.SECONDS)//设置读取超时时间
builder.writeTimeout(10L, TimeUnit.SECONDS)//设置写的超时时间
builder.connectTimeout(10L, TimeUnit.SECONDS)//设置连接超时时间
} catch (e: Exception) {
if(DEBUG){
Log.e(TAG,"",e)
}
}
return builder.build()
}
public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) {
if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 22) {
try {
val sslContext = SSLContext.getInstance("TLS")
sslContext .init(null, null, null)
val socketFactory = Tls12SocketFactory(sslContext.socketFactory)
client.sslSocketFactory(socketFactory, getDefaultTrustManager())
} catch (exc: Exception) {
if (AppEnv.bAppdebug) {
Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc)
}
try {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, null, null);
client.sslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()));
client.sslSocketFactory(socketFactory, getDefaultTrustManager())
client.connectionSpecs(specs);
} catch (Exception exc) {
if (AppEnv.bAppdebug) {
Log.e("OkHttpTLSCompat", "Error while setting TLS 1.2", exc);
}
}
}
return client;
}
https Android 5.0 以下TLS 版本过低造成的问题的更多相关文章
- Android 6.0 M userdebug版本执行adb remount失败
[FAQ18076]Android 6.0 M版本默认会打开system verified boot,即在userdebug和user版本会把system映射到dm-0设备,然后再挂载.挂载前会检查s ...
- Android 5.0及以上版本使用webview不能存储第三方Cookies解决方案
Android 5.0以上的手机使用原生WebView浏览网页,在进行登录的时候会提示验证码错误,通过查找5.0以上系统的api文档,发现5.0以上版本的webview做了较大的改动,如:同步cook ...
- tomcat https 支持android 6.0及以上版本的配置方法
<Connector port="443" protocol="HTTP/1.1" SSLEnabled="true" scheme ...
- Android 6.0及以上版本如何实现从图库中选取图片和拍照功能
XML 代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andr ...
- Android 4.0及以上版本接收开机广播BOOT_COMPLETED、开机自启动服务
1.BootCompletedReceiver.Java文件 public class BootCompletedReceiver extends BroadcastReceiver { @Overr ...
- Charles + Android 抓取Https数据包 (适用于Android 6.0及以下)
通过Charles代理,我们能很轻易的抓取手机的Http请求,因为Http属于明文传输,所以我们能直接获取到我们要抓取的内容.但是Https内容本身就是加密的,这时我们会发现内容是加密的了.本文我们来 ...
- Android 5.0 行为变更
Android 5.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更.本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更. 如果您之前发布过 Android 应用,请注意 ...
- android 8.0变更
Android 8.0 行为变更 Android 8.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更.本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更. 其中大部分变 ...
- android 8.0 适配(总结)
android 8.0 对应的 sdk 版本 26 1. 通知栏 Android 8.0 引入了通知渠道,其允许您为要显示的每种通知类型创建用户可自定义的渠道.用户界面将通知渠道称之为通知类别. 针 ...
随机推荐
- Luogu 2470 [SCOI2007]压缩
和Luogu 4302 [SCOI2003]字符串折叠 差不多的想法,区间dp 为了计算方便,我们可以假设区间[l, r]的前面放了一个M,设$f_{i, j, 0/1}$表示区间$[i, j]$中是 ...
- python的远程调试(使用pycharm)
测试环境描述1:c++调用python,操作系统环境是linux 2:pycharm安装在windows 安装步骤 1:把pycharm-debug.egg上传到linux上面. 2:使用easy_i ...
- 使用 Bulma
一.起因 最近我在学习 SASS,通过它,可以将 CSS 像编程语言一样书写. 在最近之前,我又学习了 Flex 布局,用起来很方便. 所以,我学习了 Bulma 这个纯 CSS 框架--使用 Fle ...
- [译]Javascript substring实例
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- 常用Linux命令:ls/cd/pwd/mkdir/rm/mv/cp
一.ls:列出目标目录中所有的子目录和文件 1.命令格式 ls [选项] [目录名] 2.常用参数 -a :列出目录下所有文件 -h :以容易理解的格式列出文件大小 -l :除了文件名之外,还将文件 ...
- Java50道经典习题-程序50 文件IO
题目:有五个学生,每个学生有3门课的成绩,从键盘输入以上数据(包括学生号,姓名,三门课成绩),计算出平均成绩,将原有的数据和计算出的平均分数存放在磁盘文件"stud"中. impo ...
- 海量推荐系统:mapreduce的方法
1. Motivation 2. MapReduce MapReduce是一种数据密集型并行计算框架. 待处理数据以"块"为单位存储在集群机器文件系统中(HDFS),并以(key, ...
- SQL XML示例
declare @xmlDoc xml,@id varchar(50); set @xmlDoc='<DocObjContent> <NewCtrl Id="0001&qu ...
- zancun
#include<iostream> #include<cstdio> using namespace std; ; int n; int avai[maxn], need[m ...
- 洛谷P3726 [AH2017/HNOI2017]抛硬币(组合数+扩展Lucas)
题面 传送门 题解 果然--扩展\(Lucas\)学了跟没学一样-- 我们先考虑\(a=b\)的情况,这种情况下每一个\(A\)胜的方案中\(A\)和\(B\)的所有位上一起取反一定是一个\(A\)败 ...