Привязка доверия не найдена для Android SSL-соединения


185

Я пытаюсь подключиться к блоку IIS6, работающему с сертификатом godaddy 256bit SSL, и получаю сообщение об ошибке:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

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

Вот как я подключаюсь:

HttpsURLConnection conn;              
conn = (HttpsURLConnection) (new URL(mURL)).openConnection();
conn.setConnectTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
String tempString = toString(conn.getInputStream()); 

Ответы:


78

Решение @Chrispix опасно! Доверие всем сертификатам позволяет любому сделать человека в середине атаки! Просто отправьте ЛЮБОЙ сертификат клиенту, и он примет его!

Добавьте свой сертификат (сертификаты) в пользовательский диспетчер доверия, как описано в этом посте: Доверие всем сертификатам с использованием HttpClient через HTTPS

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


1
Это нормально для работы с самогенерируемым сертификатом, но для одного (например, OP), который имеет действительную цепочку к корневому CA, это просто обходной путь для плохо настроенного сервера - см. Мой ответ.
— Стиви

4
@Stevie Принятие КАЖДОГО сертификата - это только вариант для проверки концепции, когда SSL-соединение не является частью, которую вы хотите проверить. В противном случае вам не нужно использовать SSL, если вы принимаете каждый сертификат, так как соединение небезопасно!
— Матиас Б.

1
Ах, извините, я думаю, что есть недоразумение - я полностью согласен, что никто не должен принимать каждый сертификат! :) Мой комментарий касался вашего 2-го абзаца - предложения использовать настраиваемый менеджер доверия - который, по моему мнению, должен быть последним решением, а не рекомендуемым решением.
— Стиви

2
Выступите на голову ... Я удалил «решение», которое я вставил в качестве обходного пути, чтобы не вызывать больше проблем, поскольку люди не воспринимали его как «временное решение».
— Chrispix

7
@Chrispix, вы не должны были удалять частичное исправление, это хорошо только для тестирования
— Уго Аллексис Кардона

224

Вопреки принятому ответу вам не нужен специальный менеджер доверия, вам нужно исправить конфигурацию вашего сервера!

Я столкнулся с той же проблемой при подключении к серверу Apache с неправильно установленным сертификатом dynadot / alphassl. Я подключаюсь с помощью HttpsUrlConnection (Java / Android), который бросал -

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

Фактическая проблема - неверная конфигурация сервера - протестируйте ее с http://www.digicert.com/help/ или подобной, и она даже скажет вам решение:

«Сертификат не подписан доверенным органом (проверка по отношению к корневому хранилищу Mozilla). Если вы купили сертификат в доверенном органе, вам, вероятно, просто нужно установить один или несколько промежуточных сертификатов . Обратитесь к поставщику сертификатов за помощью, выполнив это для вашего серверная платформа. "

Вы также можете проверить сертификат с помощью openssl:

openssl s_client -debug -connect www.thedomaintocheck.com:443

Вы, вероятно, увидите:

Verify return code: 21 (unable to verify the first certificate)

и ранее в выводе:

depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=21:unable to verify the first certificate`

Цепочка сертификатов будет содержать только 1 элемент (ваш сертификат):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
  i:/O=AlphaSSL/CN=AlphaSSL CA - G2

... но следует ссылаться на право подписи в цепочке на доверенное Android (Verisign, GlobalSign и т. д.):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
   i:/O=AlphaSSL/CN=AlphaSSL CA - G2
 1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
 2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA

Инструкции (и промежуточные сертификаты) для настройки вашего сервера обычно предоставляются органом, выдавшим ваш сертификат, например: http://www.alphassl.com/support/install-root-certificate.html.

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


3
Если у ОП есть доступ к конфигурации SSL серверов, к которой он подключается, это может быть решением. Но если он не является хостером службы, к которой он подключается, он должен решить проблему со своей стороны, то есть реализовать собственный менеджер доверия.
— Матиас Б

9
Ваше решение работает, без вопросов, но разве вы не согласны с тем, что это обходной путь, а не исправление основной причины? Если мне нужно подключиться к серверу из 3-х клиентов (Android, iOS, Windows Mobile), тогда мне придется применить обходной путь ко всем 3, тогда как я могу исправить сервер один раз, и все они будут «просто работать».
— Стиви

2
Спасибо, Стиви, у меня неправильно настроен сервер на 3 месяца, и только сейчас я это обнаружил! Теперь мое приложение для Android работает на 100%
— jpros

2
@ Steve Я делаю много вызовов различным API, которые совместно используют один и тот же домен, но только с одним из них происходит сбой (javax.net.ssl.SSLHandshakeException) ... есть идеи, почему это может произойти? и, кстати, сертификат SSL не является доверенным. Итак, я подумал, что все вызовы должны завершаться с одним и тем же исключением.
— честный игрок

1
@dvaey свяжись с кем-либо, кто владеет сервером, и скажи им, что их конфигурация сломана, а их https не работает должным образом - дайте им эту ссылку, чтобы доказать это digicert.com/help ... Я думаю, они будут благодарны и быстро разрешить. В противном случае вам придется предпринять один из обходных путей в других ответах, но затем вам придется либо не принимать никаких мер безопасности (игнорировать сертификаты), либо повторно развертывать приложения, когда срок действия сертификата истекает, а хранилище пользовательских трастов больше не соответствует новому. засвидетельствовано
— Стиви

17

Вы можете доверять конкретному сертификату во время выполнения.
Просто скачайте его с сервера, вставьте ресурсы и загрузите так, используя ssl-utils-android :

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

В приведенном выше примере я использовал, OkHttpClientно SSLContextможет быть использован с любым клиентом в Java.

Если у вас есть вопросы, не стесняйтесь спросить. Я автор этой маленькой библиотеки.


как насчет .pfx?
— Холецкий

2
Разве это небезопасно, поскольку любой пользователь может получить доступ к папке ресурсов для приложения, если у него есть apk?
— Патрис Андала

1
@PatriceAndala, корневые CA общедоступны, так что все в порядке
— BekaBot

17

Обновление на основе последней документации Android (март 2017 года):

Когда вы получаете этот тип ошибки:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
        at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)

проблема может быть одной из следующих:

  1. ЦС, выдавший сертификат сервера, был неизвестен
  2. Сертификат сервера не был подписан ЦС, но был самоподписан
  3. В конфигурации сервера отсутствует промежуточный ЦС

Решение состоит в том, чтобы научить HttpsURLConnectionдоверять определенному набору CA. Как? Пожалуйста, проверьте https://developer.android.com/training/articles/security-ssl.html#CommonProblems

Другие, которые используют AsyncHTTPClientиз com.loopj.android:android-async-httpбиблиотеки, пожалуйста, проверьте Setup AsyncHttpClient для использования HTTPS .


5
Что делать, если кто-то использует okhttp-клиент?
— TheLearner

Пожалуйста, проверьте ответ @ mklimek.
— user1506104

14

Если вы используете модернизацию, вам нужно настроить ваш OkHttpClient.

retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

Полный код приведен ниже.

    public class RestAdapter {

    private static Retrofit retrofit = null;
    private static ApiInterface apiInterface;

    public static OkHttpClient.Builder getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());

            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            return builder;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static ApiInterface getApiClient() {
        if (apiInterface == null) {

            try {
                retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

            } catch (Exception e) {

                e.printStackTrace();
            }


            apiInterface = retrofit.create(ApiInterface.class);
        }
        return apiInterface;
    }

}

1
Я пытаюсь использовать код, но снова получаю следующую ошибку ...
— Вишва Пратап

Это радикально небезопасно. Не используй.
— Маркиз Лорн

Спасибо! Переписал метод getUnsafeOkHttpClient()в Котлине: stackoverflow.com/a/60507560/2914140 .
— CoolMind

11

Отвечаю на очень старый пост. Но, возможно, это поможет какому-то новичку, и если ничего из вышеперечисленного не получится.

Объяснение: я знаю, что никто не хочет дерьма объяснения; скорее решение. Но в одном случае вы пытаетесь получить доступ к услуге с локального компьютера на удаленный компьютер, который не доверяет вашему компьютеру. Вы запрашиваете необходимость получить доверие от удаленного сервера.

Решение: в следующем решении предполагается, что выполнены следующие условия

  1. Попытка получить доступ к удаленному API с вашего локального компьютера.
  2. Вы создаете приложение для Android
  3. Ваш удаленный сервер находится под прокси-фильтрацией (вы используете прокси-сервер в настройках браузера для доступа к удаленной службе API, обычно к промежуточному серверу или серверу разработки)
  4. Вы тестируете на реальном устройстве

шаги:

Вам нужен файл расширения .keystore для регистрации вашего приложения. Если вы не знаете, как создать файл .keystore; затем следуют вместе со следующей секции Создать .keystore файл или в противном случае переходите к следующему разделу жестового Apk файл

Создать файл .keystore

Откройте Android Studio. Нажмите верхнее меню Build> Generate Signed APK. В следующем окне нажмите кнопку Создать новую ... кнопку. В новом окне, пожалуйста, введите данные во все поля. Помните, что поле «Два пароля», которое я рекомендую, должно иметь одинаковый пароль; не используйте другой пароль; а также помнить о пути сохранения на самом верхнее поле Key пути магазина: . После ввода всех полей нажмите кнопку ОК.

Подпишите файл Apk

Теперь вам нужно создать подписанное приложение с файлом .keystore, который вы только что создали. Следуй этим шагам

  1. Построить> Очистить проект, дождаться окончания очистки
  2. Построить> Создать подписанный APK
  3. Нажмите Choose existing...кнопку
  4. Выберите файл .keystore, который мы только что создали, в разделе « Создание файла .keystore ».
  5. Введите тот же пароль, который вы создали при создании в разделе Create .keystore file . Используйте один Key store passwordи тот же пароль для Key passwordполей и. Также введите псевдоним
  6. Нажмите кнопку Далее
  7. На следующем экране; которые могут отличаться в зависимости от ваших настроек в build.gradleфайлах, вам нужно выбрать Build Typesи Flavors.
  8. Для Build Typesвыбора releaseиз выпадающего
  9. Для Flavorsоднако это будет зависит от ваших настроек в build.gradleфайле. Выберите stagingиз этого поля. Я использовал следующие настройки в build.gradle, вы можете использовать так же, как у меня, но убедитесь, что вы измените на applicationIdимя вашего пакета

    productFlavors {
        staging {
            applicationId "com.yourapplication.package"
            manifestPlaceholders = [icon: "@drawable/ic_launcher"]
            buildConfigField "boolean", "CATALYST_DEBUG", "true"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "true"
        }
        production {
            buildConfigField "boolean", "CATALYST_DEBUG", "false"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "false"
        }
    }
  10. Нажмите два нижних Signature Versionsфлажка и нажмите Finishкнопку.

Почти готово:

Вся тяжелая работа сделана, теперь движение истины. Чтобы получить доступ к промежуточному серверу, резервное копирование которого осуществляется через прокси-сервер, необходимо выполнить некоторые настройки в реальных тестовых устройствах Android.

Настройка прокси в устройстве Android:

  1. Нажмите Настройка внутри телефона Android, а затем Wi-Fi
  2. Длительно нажмите на подключенный Wi-Fi и выберите Modify network
  3. Нажмите, Advanced optionsесли вы не видите Proxy Hostnameполе
  4. В Proxy Hostnameвъезжают в IP или имя вы хотите подключиться. Типичный промежуточный сервер будет называтьсяstg.api.mygoodcompany.com
  5. Для порта введите четырехзначный номер порта, например 9502
  6. Нажмите Saveкнопку

Одна последняя остановка:

Помните, что мы создали подписанный файл apk в разделе Sign APK File . Сейчас самое время установить этот APK-файл.

  1. Откройте терминал и перейдите в папку с подписанным файлом apk.
  2. Подключите устройство Android к вашей машине
  3. Удалите все предыдущие установленные apk-файлы с устройства Android
  4. Бегать adb install name of the apk file
  5. Если по какой-либо причине указанная выше команда возвращается с adb command not found. Введите полный путь какC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

Я надеюсь, что проблема может быть решена. Если нет, пожалуйста, оставьте мне комментарий.

Салам!


4

Сообщение об ошибке, которое я получал, было похоже, но причина в том, что самоподписанный сертификат истек. Когда была предпринята попытка клиента openssl, он дал мне причину, которая была упущена из виду, когда я проверял диалог сертификата из firefox.

Таким образом, в общем случае, если сертификат находится в хранилище ключей и имеет значение «VALID», эта ошибка исчезнет.


1
Если срок действия сертификата истек, значит, он недействителен в соответствии с рядом стандартов. Можно использовать обычай TrustManagerи использовать другой набор критериев. Но из коробки с этим вы должны работать.
— августа

4

У меня была такая же проблема при подключении от клиента Android к серверу Kurento. Сервер Kurento использует jks-сертификаты, поэтому мне пришлось конвертировать в него pem. В качестве входных данных для преобразования я использовал файл cert.pem, и это приводило к таким ошибкам. Но если вместо cert.pem использовать fullchain.pem - все в порядке.


3

Используйте https://www.ssllabs.com/ssltest/ для проверки домена.

Решение Шихаб Уддина в Котлине.

import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException

companion object {

    private val gson: Gson
    private val retrofit: Retrofit

    init {

        val okHttpClient = getUnsafeOkHttpClient() // OkHttpClient().newBuilder()
            .build()

        gson = GsonBuilder().setLenient().create()

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

    private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
        try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts: Array<TrustManager> = arrayOf(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
                }
            )
            // Install the all-trusting trust manager
            val sslContext: SSLContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
            val builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory,
                trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier { _, _ -> true }
            builder
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
}

2

У меня была та же проблема, что я обнаружил, что файл сертификата .crt, который я предоставил, пропустил промежуточный сертификат. Поэтому я спросил все файлы .crt у администратора сервера, а затем объединил их в обратном порядке.

Ex. 1. Root.crt 2. Inter.crt 3. myCrt.crt

в окнах я выполнил копию Inter.crt + Root.crt newCertificate.crt

(Здесь я проигнорировал myCrt.crt)

Затем я предоставил файл newCertificate.crt в код через inputtream. Работа сделана.


У нас тоже была такая же проблема. Промежуточный сертификат отсутствовал
— Нидин Чандран

1

Ошибка привязки доверия может произойти по многим причинам. Для меня это было просто, что я пытался получить доступ https://example.com/вместо https://www.example.com/.

Поэтому вы можете дважды проверить свои URL-адреса перед началом создания собственного диспетчера доверия (как я сделал).


0

В телефонах Gingerbread я всегда получаю эту ошибку: Trust Anchor not found for Android SSL Connectionдаже если я настроен на использование своего сертификата.

Вот код, который я использую (на языке Scala):

object Security {
    private def createCtxSsl(ctx: Context) = {
        val cer = {
            val is = ctx.getAssets.open("mycertificate.crt")
            try
                CertificateFactory.getInstance("X.509").generateCertificate(is)
            finally
                is.close()
        }
        val key = KeyStore.getInstance(KeyStore.getDefaultType)
        key.load(null, null)
        key.setCertificateEntry("ca", cer)

        val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
    tmf.init(key)

        val c = SSLContext.getInstance("TLS")
        c.init(null, tmf.getTrustManagers, null)
        c
    }

    def prepare(url: HttpURLConnection)(implicit ctx: Context) {
        url match {
            case https: HttpsURLConnection ⇒
                val cSsl = ctxSsl match {
                    case None ⇒
                        val res = createCtxSsl(ctx)
                        ctxSsl = Some(res)
                        res
                    case Some(c) ⇒ c
                }
                https.setSSLSocketFactory(cSsl.getSocketFactory)
            case _ ⇒
        }
    }

    def noSecurity(url: HttpURLConnection) {
        url match {
            case https: HttpsURLConnection ⇒
                https.setHostnameVerifier(new HostnameVerifier {
                    override def verify(hostname: String, session: SSLSession) = true
                })
            case _ ⇒
        }
    }
}

и вот код подключения:

def connect(securize: HttpURLConnection ⇒ Unit) {
    val conn = url.openConnection().asInstanceOf[HttpURLConnection]
    securize(conn)
    conn.connect();
    ....
}

try {
    connect(Security.prepare)
} catch {
    case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ ⇒
        connect(Security.noSecurity)
}

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

Этот пример кода может быть легко переведен на Java.


Решение для Android 2.3.x на случай, если это кому-то понадобится, stackoverflow.com/a/46465722/7125370
— Newbie009

0

В моем случае это происходило после обновления до Android 8.0. Самоподписанный сертификат Android, которому доверяли, использовал алгоритм подписи SHA1withRSA. Переход на новый сертификат с использованием алгоритма подписи SHA256 с RSA устранил проблему.


0

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

Все, что мне нужно было сделать, это изменить инициализацию sslContext

mySSLContext.init(null, trustAllCerts, null); 

где trustAllCertsбыл создан так:

private final TrustManager[] trustAllCerts= new TrustManager[] { new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return new java.security.cert.X509Certificate[]{};
    }

    public void checkClientTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }
} };

Надеюсь, что это пригодится.


Это я и хотел найти! Спасибо
— Oxied

Я получаю ошибку Hostname '192.168.0.16' was not verified. Я тестирую свой webapi через мой отладчик (IIS Express) локально. Есть идеи как это исправить? Спасибо :)
— Сэм

1
Это радикально небезопасно. Не используй.
— Маркиз Лорн

0

У меня была похожая проблема, и я полностью исключил стратегию доверия всем источникам.

Я делюсь здесь своим решением, примененным к приложению, внедренному в Kotlin

Сначала я бы порекомендовал использовать следующий веб-сайт для получения информации о сертификате и его действительности.

Если он не отображается как «Принятые эмитенты» в доверенном хранилище Android по умолчанию , мы должны получить этот сертификат и включить его в приложение для создания настраиваемого хранилища доверенных сертификатов.

Идеальным решением в моем случае было создание диспетчера доверия высокого уровня, который сочетает в себе пользовательское хранилище доверия и Android-хранилище по умолчанию.

Здесь он представляет высокоуровневый код, используемый для настройки OkHttpClient, который он использовал с Retrofit.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

        val trustManagerWrapper = createX509TrustManagerWrapper(
            arrayOf(
                getCustomX509TrustManager(),
                getDefaultX509TrustManager()
            )
        )

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

        val sslSocketFactory = createSocketFactory(trustManagerWrapper)
        httpClientBuild.sslSocketFactory(sslSocketFactory, trustManagerWrapper)

    }

Таким образом, я мог общаться с сервером с самозаверяющим сертификатом и с другими серверами с сертификатом, выданным доверенным органом сертификации.

Это все, я надеюсь, что это может кому-то помочь.


0

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

https://stackoverflow.com/a/60102517/114265


только для API 24+
— BekaBot

@BekaBot - это, вероятно, так, но в соответствии с документацией 23 и ниже доверяет сертификатам пользователей по умолчанию. По умолчанию защищенные соединения (использующие протоколы, такие как TLS и HTTPS) из всех приложений доверяют предустановленным системным ЦС и приложениям, ориентированным на Android 6.0. (Уровень API 23) и ниже также доверяют добавленному хранилищу CA по умолчанию
— GR Envoy

-1
**Set proper alias name**
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC");
            X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
            String alias = cert.getSubjectX500Principal().getName();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);

-2

Я также столкнулся с той же проблемой. Я просто удаляю hhtps в http, например

final public static String ROOT_URL = "https://example.com"; в final public static String ROOT_URL = "http://example.com";

Наконец, я решил эту проблему.


Конечно, это просто удаление защиты SSL из уравнения, что, вероятно, является плохой идеей для производственной среды.
— Драконьи мысли

Это действительно не решение, удаляющее безопасность SSL.
— omega1
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.