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

s-h*_*ter 1 android exoplayer tls1.2

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

根据此Android 文档,API 16+ 支持TLS 1.11.2 ,但在 API 20+ 之前默认不启用。我找到了一些解决方案(此处此处此处此处),用于启用 OkHttp 的 TLS 1.1 和 1.2 支持。如何启用 Exoplayer 的 TLS 1.1/1.2 支持?我发现的关于 Exoplayer TLS 1.1/1.2 支持的唯一帖子来自此 github问题,该问题建议改为在此处提出问题。

“07-27 13:21:09.817 8925-9065/com.ftsgps.monarch E/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警报握手失败(外部/openssl/ssl/s23_clnt.c:744 0x689d8f10:0x00000 000) ”

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

Zoh*_*mir 5

DefaultHttpDataSource使用HttpsURLConnection它有一个默认的静态字段SSLSocketFactory。除非在实例上调用,否则所有新实例都HttpsURLConnection将分配此默认值。因此从技术上讲,如果您在实例化之前调用 set the default ,它应该可以工作:SSLSocketFactorysetSSLSocketFactory()SSLSocketFactory DefaultHttpsDataSource

HttpsURLConnection.setDefaultSSLSocketFactory(new MyCustomSSLSocketFactory());
Run Code Online (Sandbox Code Playgroud)

其中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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但请记住,这可能会在意想不到的地方改变您的应用程序的行为(极不可能,但谨慎一点总没有坏处),为了避免这种情况,您可以在使用DefaultHttpDataSource.

然而,还有另一种更可靠的解决方案。 您可以在构造函数中使用OkHttpDataSource可以传递实例的位置。OkHttpClientOkHttpClient实例可以配置为使用我们的自定义SSLSocketFactory. 它看起来像这样:

okhttpclient.sslSocketFactory(new MyCustomSSLSocketFactory());
Run Code Online (Sandbox Code Playgroud)
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;
    }
}
Run Code Online (Sandbox Code Playgroud)