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

问题描述 投票:1回答:2

根据此Android doc,API 16+支持TLS 1.1和1.2,但直到API 20+才默认启用。我找到了一些解决方案(herehereherehere)来启用对OkHttp的TLS 1.1和1.2支持。如何为Exoplayer启用TLS 1.1 / 1.2支持?我发现唯一支持Exoplayer TLS 1.1 / 1.2的帖子来自此github issue,建议改在此处提问。

“” 07-27 13:21:09.817 8925-9065 / com.ftsgps.monarchE / ExoPlayerImplInternal:源错误。com.google.android.exoplayer2.upstream.HttpDataSource $ HttpDataSourceException:无法连接到https://liveStream/LIVE-0089000D05/manifest.mpd在com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:194)在com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:147)在com.google.android.exoplayer2.upstream.DataSourceInputStream.checkOpened(DataSourceInputStream.java:102)在com.google.android.exoplayer2.upstream.DataSourceInputStream.open(DataSourceInputStream.java:65)在com.google.android.exoplayer2.upstream.ParsingLoadable.load(ParsingLoadable.java:129)在com.google.android.exoplayer2.upstream.Loader $ LoadTask.run(Loader.java:308)在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:587)在java.lang.Thread.run(Thread.java:841)导致原因:javax.net.ssl.SSLHandshakeException:javax.net.ssl.SSLProtocolException:SSL握手已中止:ssl = 0x722c3af8:SSL库失败,通常是协议错误错误:14077410:SSL例程:SSL23_GET_SERVER_HELLO:sslv3警报握手失败(external / openssl / ssl / s23_clnt.c:7440x689d8f10:0x00000000)“

仅在API 21版本(棒棒糖)以下才发生这种情况。服务器是使用TLS1.2协议,Lollipop以下的Android不支持该协议版本。

android tls1.2 exoplayer
2个回答
1
投票

DefaultHttpDataSource使用HttpsURLConnection,它具有默认SSLSocketFactory的静态字段。除非在实例上调用HttpsURLConnection,否则所有SSLSocketFactory的新实例都将分配此默认值setSSLSocketFactory()。因此从技术上讲,如果您调用设置默认的SSLSocketFactory before实例化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;
    }
}

但是请记住,这可能会在意外的地方更改应用程序的行为(极不可能,但从不会变得谨慎),为避免这种情况,您可以在使用DefaultHttpDataSource之后将Default SSLSocketFactory恢复为旧的SSLSocketFactory。 。

但是,还有另一个更可靠的解决方案。您可以使用OkHttpDataSource,可以在构造函数中传递OkHttpClient实例。可以将该OkHttpClient实例配置为使用我们的自定义SSLSocketFactory。它看起来像这样:

okhttpclient.sslSocketFactory(new MyCustomSSLSocketFactory());
DataSource dataSource = new DefaultUriDataSource(context, bandwidthMeter,
    new OkHttpDataSource(okHttpClient, userAgent, null, bandwidthMeter));

0
投票

经过一些挖掘之后,我要做的就是使用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 handshake aborted: Failure in SSL library, usually a protocol error

https://guides.codepath.com/android/Using-OkHttp#enabling-tls-v1-2-on-older-devices

© www.soinside.com 2019 - 2024. All rights reserved.