Android Включить TLSv1.2 в OKHttp - программирование
Подтвердить что ты не робот

Android Включить TLSv1.2 в OKHttp

Я использую OKHttp для моего проекта. Я хочу включить TLSv1.2 для моего служебного вызова. может ли любой орган сказать мне, как включить его.

4b9b3361

Ответ 1

См. OkHttps Документация HTTPS.

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) 
  .tlsVersions(TlsVersion.TLS_1_2)
  .cipherSuites( 
     CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
     CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
     CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
  .build();
OkHttpClient client = ... 
client.setConnectionSpecs(Collections.singletonList(spec));

Ответ 2

Насколько я знаю, OKHttp не включает собственные библиотеки SSL/TLS, поэтому он просто использует стандартный SSLSocket, предоставляемый Android.

Какие версии TLS поддерживаются (и включены), зависит от используемой версии Android. На некоторых телефонах TLS 1.2 поддерживается, но не включен по умолчанию. В таких случаях вы можете включить его, внедрив пользовательскую оболочку SSLSocketFactory, которая внутренне использует SSLS файл по умолчанию и вызывает setEnabledProtocols(new String{"TLS1.2"}) для каждого созданного Socket.

Ответ 3

Проверить мой код! Работайте идеально!

private void checkTls() {
    if (android.os.Build.VERSION.SDK_INT < 21) {
        try {
            ProviderInstaller.installIfNeededAsync(this, new ProviderInstaller.ProviderInstallListener() {
                @Override
                public void onProviderInstalled() {
                }

                @Override
                public void onProviderInstallFailed(int i, Intent intent) {
                }
            });
        } catch (Exception e) {
            finish();
            e.printStackTrace();
        }
    }
}

Ответ 4

Оказывается, мое решение очень похоже на Ken (кроме Java). Я нашел здесь, хотя пришлось сделать пару небольших изменений, чтобы заставить его работать. Надеюсь, это работает "из коробки" для других.

public class TLSSocketFactoryCompat extends SSLSocketFactory {

private SSLSocketFactory internalSSLSocketFactory;

public TLSSocketFactoryCompat() throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, null, null);
    internalSSLSocketFactory = context.getSocketFactory();
}

public TLSSocketFactoryCompat(TrustManager[] tm) throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, tm, new java.security.SecureRandom());
    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)) {
        //Create list of supported protocols
        ArrayList<String> supportedProtocols = new ArrayList<>();
        for (String protocol : ((SSLSocket)socket).getEnabledProtocols()) {

            //Log.d("TLSSocketFactory", "Supported protocol:" + protocol);
            //Only add TLS protocols (don't want ot support older SSL versions)
            if (protocol.toUpperCase().contains("TLS")) {
                supportedProtocols.add(protocol);
            }
        }
        //Force add TLSv1.1 and 1.2 if not already added
        if (!supportedProtocols.contains("TLSv1.1")) {
            supportedProtocols.add("TLSv1.1");
        }
        if (!supportedProtocols.contains("TLSv1.2")) {
            supportedProtocols.add("TLSv1.2");
        }

        String[] protocolArray = supportedProtocols.toArray(new String[supportedProtocols.size()]);
        /*for (int i = 0; i < protocolArray.length; i++) {
            Log.d("TLSSocketFactory", "protocolArray[" + i + "]" + protocolArray[i]);
        }*/

        //enable protocols in our list
        ((SSLSocket)socket).setEnabledProtocols(protocolArray);
    }
    return socket;
}

}

Использование:

    OkHttpClient httpClient = new OkHttpClient();
    //Add Custom SSL Socket Factory which adds TLS 1.1 and 1.2 support for Android 4.1-4.4
    try {
        httpClient.setSslSocketFactory(new TLSSocketFactoryCompat());
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

Ответ 5

Это в основном то же самое, что и ответ выше, но я чувствую, что образец кода был бы полезен для всех, кто приземлился здесь и не успевает навигации по ландшафту java ssl.

Что в конечном итоге закончилось для меня, было основано на проблеме, о которой сообщалось здесь: https://github.com/mattleibow/square-bindings/issues/1
из этого gist https://gist.github.com/mattleibow/c8abfa323db094b820cc

Обратите внимание, что эти образцы кода находятся в С#/Xamarin, но могут быть легко переведены в java.

internal class CompleteSSLSocketFactory : SSLSocketFactory
{
    private readonly SSLSocketFactory innerFactory;

    public CompleteSSLSocketFactory (SSLSocketFactory innerFactory)
    {
        this.innerFactory = innerFactory;
    }

    public override string[] GetDefaultCipherSuites ()
    {
        return innerFactory.GetDefaultCipherSuites ();
    }

    public override string[] GetSupportedCipherSuites ()
    {
        return innerFactory.GetSupportedCipherSuites ();
    }

    public override Socket CreateSocket ()
    {
        return MakeSocketSafe (innerFactory.CreateSocket ());
    }

    public override Socket CreateSocket (Socket s, string host, int port, bool autoClose)
    {
        return MakeSocketSafe (innerFactory.CreateSocket (s, host, port, autoClose));
    }

    public override Socket CreateSocket (string host, int port)
    {
        return MakeSocketSafe (innerFactory.CreateSocket (host, port));
    }

    public override Socket CreateSocket (string host, int port, InetAddress localHost, int localPort)
    {
        return MakeSocketSafe (innerFactory.CreateSocket (host, port, localHost, localPort));
    }

    public override Socket CreateSocket (InetAddress host, int port)
    {
        return MakeSocketSafe (innerFactory.CreateSocket (host, port));
    }

    public override Socket CreateSocket (InetAddress address, int port, InetAddress localAddress, int localPort)
    {
        return MakeSocketSafe (innerFactory.CreateSocket (address, port, localAddress, localPort));
    }

    private Socket MakeSocketSafe (Socket socket)
    {
        var sslSocket = socket as SSLSocket;
        if (sslSocket != null) {
            // enable all supported protocols for this socket
            sslSocket.SetEnabledProtocols (sslSocket.GetSupportedProtocols ());
            sslSocket.SetEnabledCipherSuites (sslSocket.GetSupportedCipherSuites ());
        }
        return socket;
    }
}

И затем назовем это как:

// this.client is an OkHttpClient
if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.Lollipop) {
    this.client.SetSslSocketFactory(new CompleteSSLSocketFactory(HttpsURLConnection.DefaultSSLSocketFactory));
}

Это сработало для меня, проверено на API 19.