首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何为Exoplayer启用/支持TLS 1.1、1.2?

如何为Exoplayer启用/支持TLS 1.1、1.2?
EN

Stack Overflow用户
提问于 2019-10-18 19:01:55
回答 2查看 2.3K关注 0票数 1

错误: SSL握手中止: ssl=0x676a5680: SSL库中的失败,通常是协议错误

根据这个Android文档,API 16+支持TLS1.11.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协议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-06 08:39:58

在深入研究之后,我所要做的就是使用ProviderInstaller在应用程序类中启用TLS1.2。我已经用服务器提供的不接受TLS1.0的视频内容来验证它,而且它起了作用。

代码语言:javascript
复制
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

票数 3
EN

Stack Overflow用户

发布于 2019-11-04 12:55:22

DefaultHttpDataSource使用HttpsURLConnection,它为默认SSLSocketFactory提供了一个静态字段。所有新的HttpsURLConnection实例都将分配这个默认的SSLSocketFactory,除非对实例调用setSSLSocketFactory()。因此,从技术上讲,如果在SSLSocketFactory实例化DefaultHttpsDataSource之前调用set默认的DefaultHttpsDataSource,那么它应该可以工作:

代码语言:javascript
复制
HttpsURLConnection.setDefaultSSLSocketFactory(new MyCustomSSLSocketFactory());

在这里,MyCustomSSLSocketFactoy看起来可能是这样的:

代码语言:javascript
复制
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。看起来会是这样的:

代码语言:javascript
复制
okhttpclient.sslSocketFactory(new MyCustomSSLSocketFactory());
代码语言:javascript
复制
DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter,
    new OkHttpDataSource(okHttpClient, userAgent, null, bandwidthMeter));
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58456778

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档