错误: SSL握手中止: ssl=0x676a5680: SSL库中的失败,通常是协议错误
根据这个Android文档,API 16+支持TLS1.1和1.2,但默认情况下只有API20+才能启用。我找到了一些解决方案(这里、这里、这里和这里)来支持TLS1.1和1.2对OkHttp的支持。如何启用对Exoplayer的TLS 1.1/1.2支持?我为Exoplayer TLS 1.1/1.2支持找到的唯一一篇文章来自这个github 问题,它建议在这里提出这个问题。
"07-27 13:21:09.817 8925-9065/com.ftsgps.monarchE/ExoPlayerImpl内部:源错误。com.google.android.exoplayer2.upstream.HttpDataSource$HttpDataSourceException:无法连接到com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:194)的https://liveStream/LIVE-0089000D05/manifest.mpd at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:147) at com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:102) at com.google.android.exoplayer2.upstream.DataSourceInputStream.open(DataSourceInputStream.java:65) at com.google.android.exoplayer2.upstream.ParsingLoadable.load(ParsingLoadable.java:129) at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:308) 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):javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL握手中止: ssl=0x722c3af8: SSL库失败,通常是协议错误:14077410:ssl routines:SSL23_GET_SERVER_HELLO:sslv3警报握手失败(外部/openssl/ssl/s23_clnt.c:7440x689d8f10:0x00000000)“ 这种情况只发生在API 21版本(棒棒糖)下面。服务器正在使用TLS1.2协议,Lollipop版本下的Android不支持TLS1.2 1.2协议。
发布于 2019-11-06 08:39:58
在深入研究之后,我所要做的就是使用ProviderInstaller在应用程序类中启用TLS1.2。我已经用服务器提供的不接受TLS1.0的视频内容来验证它,而且它起了作用。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
// Google Play will install latest OpenSSL
ProviderInstaller.installIfNeeded(getApplicationContext());
SSLContext sslContext;
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
sslContext.createSSLEngine();
} catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException
| NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
}
}参考资料:
Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL握手中止: SSL库失败,通常是协议错误
https://guides.codepath.com/android/Using-OkHttp#enabling-tls-v1-2-on-older-devices
发布于 2019-11-04 12:55:22
DefaultHttpDataSource使用HttpsURLConnection,它为默认SSLSocketFactory提供了一个静态字段。所有新的HttpsURLConnection实例都将分配这个默认的SSLSocketFactory,除非对实例调用setSSLSocketFactory()。因此,从技术上讲,如果在SSLSocketFactory实例化DefaultHttpsDataSource之前调用set默认的DefaultHttpsDataSource,那么它应该可以工作:
HttpsURLConnection.setDefaultSSLSocketFactory(new MyCustomSSLSocketFactory());在这里,MyCustomSSLSocketFactoy看起来可能是这样的:
class MyCustomSSLSocketFactory extends SSLSocketFactory {
private javax.net.ssl.SSLSocketFactory internalSSLSocketFactory;
public MyCustomSSLSocketFactory () throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
}
return socket;
}
}但是,请记住,这可能会改变应用程序在意想不到的地方的行为(非常不可能,但也不会伤害到谨慎),为了避免这种情况,您可以在使用SSLSocketFactory后将默认的DefaultHttpDataSource恢复为旧的。
然而,还有另一种更可靠的解决方案:,您可以使用OkHttpDataSource在构造函数中传递OkHttpClient实例。这个OkHttpClient实例可以配置为使用我们的自定义SSLSocketFactory。看起来会是这样的:
okhttpclient.sslSocketFactory(new MyCustomSSLSocketFactory());DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter,
new OkHttpDataSource(okHttpClient, userAgent, null, bandwidthMeter));https://stackoverflow.com/questions/58456778
复制相似问题