okHTTP Невозможно найти приемлемые протоколы (Android)

Извините за мой английский. Я пытаюсь использовать в феврале OKhttp, и я использую https для запроса. Теперь у меня есть ошибка, когда я пытаюсь опубликовать мой пример, это ошибка:

java.net.UnknownServiceException: Unable to find acceptable protocols. isFallback=false, modes=[ConnectionSpec(cipherSuites=[TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA], tlsVersions=[TLS_1_2], supportsTlsExtensions=true)], supported protocols=[SSLv3, TLSv1]

Я пытаюсь это исправить, но я не могу этого сделать. Я не знаю, что у меня есть эта ошибка

И ниже мой код:

public class PostOKhttp extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String...ulr) {
            Response response = null;
            OkHttpClient client = new OkHttpClient();
            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,
                            CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
                            CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
                            CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                            CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                            CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
                            CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
                            CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
                    .build();
            client.setConnectionSpecs(Collections.singletonList(spec));

            RequestBody postForm = new FormEncodingBuilder()
                    .add("name", "name")
                    .build();

            Request request = new Request.Builder()
                    .url(ulr[0])
                    .addHeader("id", "--")
                    .addHeader("key", "--")
                    .post(postForm)
                    .build();

            try {
                response = client.newCall(request).execute();
                Log.e("post", response.body().string());

            } catch (Exception e) {
                Log.e("error", e.toString());
            }
            return null;

        }

        @Override
        protected void onPostExecute(String result) {

        }

UDP:

Используйте CertificatePinner

я добавляю этот код

String link = "example.net";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
                    .add(link, "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=")
                    .add(link, "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=")
                    .add(link, "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=")
                    .add(link, "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")
                    .build();

            client.setCertificatePinner(certificatePinner);

Теперь у меня есть эта ошибка:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

2 ответа

На самом деле проблема в том, что TLSv1.1 и TLSv1.2 не включены на Android <5 по умолчанию, и для подключения с использованием этих последних безопасных протоколов мы должны включить на устройствах Android <5.

Поскольку по умолчанию устройство Android выбирает наивысший поддерживаемый протокол для установления соединения, но наивысший / новейший безопасный протокол (например, TLSV1.1 или TLSV1.2) не включен по умолчанию (включены только SSLV3.0 или TLSV1.0).

Включение TLSV1.1 и TLSV1.2 в Android <5

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

/**
 * @author Bajrang Hudda
 */

    public class MyTLSSocketFactory extends SSLSocketFactory {

        private SSLSocketFactory internalSSLSocketFactory;

        public MyTLSSocketFactory() 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;
        }
    }

А теперь добавь это в свой O хтпклиент -

 protected static OkHttpClient getHttpClient(long timeout){

        String hostname = Constants.HOST_NAME_DEBUG;
        CertificatePinner certificatePinner = new CertificatePinner.Builder()
                .add(hostname, "sha1/mBN/TTGneHe2Hq0yFG+SRt5nMZQ=")
                .add(hostname, "sha1/6CgvsAgBlX3PYiYRGedC0NZw7ys=")
                .build();

        //specifying the specs; this is impotent otherwise android <5 won't work 
        //And do note to include the android < 5 supported specs.
        ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                .tlsVersions(TlsVersion.TLS_1_1, 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,
                        CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                        CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
                .build();

        final OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setCertificatePinner(certificatePinner);
        okHttpClient.setConnectionSpecs(Collections.singletonList(spec));
        try
        {
            // enabling the tlsv1.1 and tlsv.2
            okHttpClient.setSslSocketFactory(new MyTLSSocketFactory()); 
        } catch (KeyManagementException e)
        {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        return okHttpClient;
    }

А теперь, наконец, добавьте его в свой комплект -

 RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint(Constants.API_URL)
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setErrorHandler(new ErrorHandler())
                .setClient(getHttpClient())
                .setRequestInterceptor(new SecureHeaderInterceptor(null))
                .build();

Вот и все, Happy Coding:-)

Вам нужно использовать ProviderInstaller проверить и установить при необходимости поддержку TLS. Используйте что-то подобное в своей записи Activity и это должно сработать. Проверьте больше информации здесь

protected void checkTls() {
    if (android.os.Build.VERSION.SDK_INT < 21) {
        try {
            ProviderInstaller.installIfNeededAsync(this, new ProviderInstaller.ProviderInstallListener() {
                @Override
                public void onProviderInstalled() {
                    SSLContext sslContext = null;
                    try {
                        sslContext = SSLContext.getInstance("TLSv1.2");
                        sslContext.init(null, null, null);
                        SSLEngine engine = sslContext.createSSLEngine();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    }

                }

                @Override
                public void onProviderInstallFailed(int i, Intent intent) {
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Другие вопросы по тегам