Привязка доверия не найдена для Android SSL-соединения
Я пытаюсь подключиться к блоку IIS6, на котором запущен годовой 256-битный 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());
26 ответов
Решение @Chrispix опасно! Доверие всем сертификатам позволяет любому сделать человека в середине атаки! Просто отправьте ЛЮБОЙ сертификат клиенту, и он примет его!
Добавьте свой сертификат (сертификаты) в настраиваемый менеджер доверия, как описано в этом посте: Доверие всем сертификатам с использованием HttpClient через HTTPS
Хотя установить безопасное соединение с настраиваемым сертификатом немного сложнее, он обеспечит вам требуемую безопасность шифрования ssl без опасности попадания человека в центр атаки!
Вопреки принятому ответу вам не нужен собственный менеджер доверия, вам нужно исправить конфигурацию вашего сервера!
Я столкнулся с той же проблемой при подключении к серверу 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.
Если вы используете модернизацию, вам нужно настроить ваш 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;
}
}
Обновление на основе последней документации 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)
проблема может быть одной из следующих:
- CA, выдавший сертификат сервера, был неизвестен
- Сертификат сервера не был подписан ЦС, но был самоподписан
- В конфигурации сервера отсутствует промежуточный ЦС
Решение состоит в том, чтобы научить HttpsURLConnection
доверять определенному набору CA. Как? Пожалуйста, проверьте https://developer.android.com/training/articles/security-ssl.html
Другие, которые используют AsyncHTTPClient
от com.loopj.android:android-async-http
библиотека, пожалуйста, проверьте настройку AsyncHttpClient для использования HTTPS.
Вы можете доверять конкретному сертификату во время выполнения.
Просто скачайте его с сервера, вставьте ресурсы и загрузите, как это, используя ssl-utils-android:
OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());
В приведенном выше примере я использовал OkHttpClient
но SSLContext
может использоваться с любым клиентом в Java.
Если у вас есть вопросы, не стесняйтесь спросить. Я автор этой маленькой библиотеки.
Отвечаю на очень старый пост. Но, возможно, это поможет какому-то новичку, и если ничего из вышеперечисленного не сработает.
Объяснение: я знаю, что никто не хочет дерьма объяснения; скорее решение. Но в одном случае вы пытаетесь получить доступ к услуге с локального компьютера на удаленный компьютер, который не доверяет вашему компьютеру. Вы запрашиваете необходимость получить доверие от удаленного сервера.
Решение. В следующем решении предполагается, что выполнены следующие условия.
- Попытка получить доступ к удаленному API с вашего локального компьютера.
- Вы создаете приложение для Android
- Ваш удаленный сервер находится под прокси-фильтрацией (вы используете прокси-сервер в настройках вашего браузера для доступа к удаленной службе API, обычно к промежуточному серверу или серверу разработки)
- Вы тестируете на реальном устройстве
шаги:
Вам нужен файл расширения.keystore для регистрации вашего приложения. Если вы не знаете, как создать файл.keystore; затем следуйте указаниям следующего раздела. Создайте файл.keystore или перейдите к следующему разделу.
Создать файл.keystore
Откройте Android Studio. Нажмите верхнее меню Build > Generate Signed APK. В следующем окне нажмите кнопку Создать новый... В новом окне, пожалуйста, введите данные во все поля. Помните, что поле "Два пароля", которое я рекомендую, должно иметь одинаковый пароль; не используйте другой пароль; а также запомните путь сохранения вверху самого поля Путь к хранилищу ключей:. После ввода всех полей нажмите кнопку ОК.
Подпишите файл Apk
Теперь вам нужно создать подписанное приложение с файлом.keystore, который вы только что создали. Следуй этим шагам
- Построить> Очистить проект, дождаться окончания очистки
- Построить> Создать подписанный APK
- Нажмите
Choose existing...
кнопка - Выберите файл.keystore, который мы только что создали, в разделе " Создание файла.keystore ".
- Введите тот же пароль, который вы создали при создании в разделе " Создание файла.keystore ". Используйте тот же пароль для
Key store password
а такжеKey password
поля. Также введите псевдоним - Нажмите кнопку Далее
- На следующем экране; которые могут отличаться в зависимости от ваших настроек в
build.gradle
файлы, вам нужно выбратьBuild Types
а такжеFlavors
, - Для
Build Types
выбиратьrelease
из выпадающего За
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" } }
Нажмите два нижних
Signature Versions
флажки и нажмитеFinish
кнопка.
Почти готово:
Вся тяжелая работа сделана, теперь движение истины. Чтобы получить доступ к промежуточному серверу, резервное копирование которого осуществляется через прокси-сервер, необходимо выполнить некоторые настройки в реальных тестовых устройствах Android.
Настройка прокси в устройстве Android:
- Нажмите Настройка внутри телефона Android, а затем Wi-Fi
- Длительно нажмите на подключенный Wi-Fi и выберите
Modify network
- Нажмите на
Advanced options
если вы не видитеProxy Hostname
поле - в
Proxy Hostname
введите IP-адрес хоста или имя, которое вы хотите подключить. Типичный промежуточный сервер будет называтьсяstg.api.mygoodcompany.com
- Для порта введите четырехзначный номер порта, например
9502
- Ударь
Save
кнопка
Одна последняя остановка:
Помните, что мы сгенерировали подписанный файл apk в разделе Sign APK File. Сейчас самое время установить этот APK-файл.
- Откройте терминал и перейдите в папку с подписанным файлом apk.
- Подключите устройство Android к вашей машине
- Удалите все предыдущие установленные apk-файлы с устройства Android
- Бежать
adb install
name of the apk file
- Если по какой-либо причине указанная выше команда вернется с
adb command not found
, Введите полный путь какC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe
install
name of the apk file
Я надеюсь, что проблема может быть решена. Если нет, пожалуйста, оставьте мне комментарий.
Салам!
Используйте 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)
}
}
У меня возникла та же проблема при попытке использовать внешний веб-сервис, который использует самоподписанный сертификат для предоставления своей тестовой версии. Вот шаги, которые я использовал для глобального решения проблемы (они будут применяться к любой используемой вами платформе: Retrofit, oKhttp, HttpUrlConnection).
- Загрузите домен в Chrome ( https://dev.thedomain.private )
- Экспортируйте сертификат в формате .der (
padlock symbol
рядом с URL-адресом, затемdetails
затемexport
и выберитеder
формат) - Сохраните дер в сырую папку.
res/raw/dev_thedomain_private.der
- Создайте файл конфигурации безопасности в разделе
resources/xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">dev.thedomain.private</domain>
<trust-anchors>
<certificates src="@raw/dev_thedomain_private"/>
</trust-anchors>
</domain-config>
</network-security-config>
- ссылка на конфигурацию безопасности в вашем манифесте под тегом приложения
<application
android:networkSecurityConfig="@xml/network_security_config"
Вы закончили! Теперь сертификату будут доверять...
У меня была та же проблема, что я обнаружил, что файл сертификата.crt, который я предоставил, пропустил промежуточный сертификат. Поэтому я спросил все файлы.crt у администратора сервера, а затем объединил их в обратном порядке.
Ex. 1. Root.crt 2. Inter.crt 3. myCrt.crt
в окнах я выполнил копию Inter.crt + Root.crt newCertificate.crt
(Здесь я проигнорировал myCrt.crt)
Затем я предоставил файл newCertificate.crt в код с помощью inputtream. Работа сделана.
Я знаю, что вам не нужно доверять всем сертификатам, но в моем случае у меня были проблемы с некоторыми средами отладки, где у нас были самозаверяющие сертификаты, и мне требовалось грязное решение.
Все, что мне нужно было сделать, это изменить инициализацию 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 {
}
} };
Надеюсь, что это пригодится.
В моем случае корневой и промежуточный сертификаты были успешно установлены, но я все равно получил сообщение «Якорь доверия для пути сертификации не найден». исключение!. После раскопок документа Android выяснилось, что по умолчанию безопасные соединения (с использованием таких протоколов, как TLS и HTTPS) из всех приложений доверяют предварительно установленным системным центрам сертификации, а приложения, ориентированные на Android 6.0 (уровень API 23) и ниже, также доверяют пользователю добавлен магазин CA по умолчанию. Если ваше приложение работает в ОС с уровнем api выше 23, вы должны явно разрешить приложению доверять CA, добавленному пользователем, добавив его адрес в network_security_config, как показано ниже:
<domain-config>
<domain includeSubdomains="true">PUT_YOUR_SERVER_ADDERESS</domain>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</domain-config>
У меня была такая же проблема при подключении с Android-клиента к серверу Kurento. Сервер Kurento использует jks-сертификаты, поэтому мне пришлось конвертировать в него pem. В качестве входных данных для преобразования я использовал файл cert.pem, и это приводило к таким ошибкам. Но если использовать fullchain.pem вместо cert.pem - все в порядке.
Сообщение об ошибке, которое я получал, было похоже, но причина в том, что самоподписанный сертификат истек. Когда была предпринята попытка клиента openssl, он дал мне причину, которая была упущена из виду, когда я проверял диалог сертификата из firefox.
Таким образом, в общем случае, если сертификат находится в хранилище ключей и имеет значение "VALID", эта ошибка исчезнет.
Ошибка привязки доверия может произойти по многим причинам. Для меня это было просто, что я пытался получить доступ https://example.com/
вместо https://www.example.com/
,
Поэтому вы можете дважды проверить свои URL-адреса, прежде чем приступить к созданию собственного диспетчера доверия (как я).
В пряничных телефонах я всегда получаю эту ошибку: 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.
Я знаю, что это очень старая статья, но я наткнулся на эту статью, когда пытался решить проблемы с якорем доверия. Я опубликовал, как я это исправил. Если вы предварительно установили корневой центр сертификации, вам необходимо добавить конфигурацию в манифест.
Иногда это происходит, когда администраторы неправильно устанавливают сертификат. Проверьте URL здесь https://www.sslshopper.com/ssl-checker.html.
В моем случае произошла ошибка
Сертификату доверяют не все веб-браузеры. Возможно, вам потребуется установить промежуточный / цепной сертификат, чтобы связать его с доверенным корневым сертификатом. Узнайте больше об этой ошибке. Вы можете исправить это, следуя инструкциям по установке сертификата GlobalSign для вашей серверной платформы. Обратите внимание на разделы о промежуточных сертификатах.
У меня была аналогичная проблема, и я полностью исключил стратегию доверия всем источникам.
Я поделюсь своим решением, примененным к приложению, реализованному на 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)
}
Таким образом, я мог общаться с сервером с помощью самозаверяющего сертификата и с другими серверами с сертификатом, выданным доверенным органом сертификации.
Вот и все, надеюсь, это кому-то поможет.
Как уже упоминалось, сертификату не доверяют. Решением было бы получить этот сертификат и включить его в качестве доверенного сертификата в ваш http-клиент.
Извлеките сертификат сервера, как показано здесь: Использование openssl для получения сертификата с сервера.
Затем создайте SSLSocketFactory для клиента HttpsURLConnection, как показано ниже.
public static void main(String[] args) throws IOException {
SSLFactory sslFactory = SSLFactory.builder()
.withDefaultTrustMaterial() // JDK trusted certificates
.withSystemTrustMaterial() // Android system trusted certificates
.withTrustMaterial("/path/to/truststore.p12", "password".toCharArray()) // your custom list of trusted certificates
.build();
HttpsURLConnection connection = (HttpsURLConnection) (new URL("https://api.chucknorris.io/jokes/random")).openConnection();
connection.setSSLSocketFactory(sslFactory.getSslSocketFactory());
connection.setHostnameVerifier(sslFactory.getHostnameVerifier());
}
Приведенный выше пример относится к хорошо известному HttpsURLConnection. Однако, если вы используете другой клиент, это также может быть полезно, поскольку оно содержит список из почти 50 различных http-клиентов для настройки SSL, см. здесь: Пример конфигурации SSL HTTP-клиента.
Должен сказать, что приведенный выше фрагмент основан на библиотеке, которую я предоставляю здесь: GitHub — SSLContext Kickstart , которую можно включить со следующим фрагментом в ваш файл сборки Gradle:
implementation("io.github.hakky54:sslcontext-kickstart:8.1.6")
В моем случае сертификат на веб-сайте был правильным (издатель = GlobalSign RSA OV SSL CA 2018), но файл сертификата, который я загружал, был неправильным из-за того, что антивирус «перехватывал» сертификат и доставлял новый другой сертификат для загрузить из браузеров (Эмитент = ESET SSL Filter CA) !!!
Убедитесь, что в файле сертификата указан правильный эмитент.
**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);
В моем случае это происходило после обновления до Android 8.0. Самоподписанный сертификат Android, которому доверяли, использовал алгоритм подписи SHA1withRSA. Переход на новый сертификат с помощью алгоритма подписи SHA256 с RSA устранил проблему.
Я использую эти методы, один из которых в решениях выше работает для меня: Во-первых:
public okhttp3.OkHttpClient 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();
okhttp3.OkHttpClient.Builder builder = new
okhttp3.OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory,
(X509TrustManager)trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession
session) {
return true;
}
});
okhttp3.OkHttpClient okHttpClient = builder.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Второй:
@SuppressLint("TrulyRandom")
public static void handleSSLHandshake() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{new
X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[]
certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[]
certs, String authType) {
}
}};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new
HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
} catch (Exception ignored) {
}
}
и: поместите эти библиотеки в свой путь к классам:
implementation 'com.squareup.okhttp:okhttp:2.3.0'
implementation 'com.squareup.okhttp:okhttp-urlconnection:2.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-
core:3.3.0'
убедитесь, что вы называете их в своем классе
Я решил свою проблему, изменив
https://example.com/
к
http://example.com/
так как на сервере не было SSL-сертификата.
Итак, проверьте URL-адрес вашего сервера и измените его соответственно
Relpcae ваш клиент Как показано ниже var httpClient = new HttpClient(new System.Net.Http.HttpClientHandler());
Сменить https на http
Я тоже столкнулся с такой же проблемой. Я просто удаляю https на http, например
final public static String ROOT_URL = "https://example.com";
к
final public static String ROOT_URL = "http://example.com";
В конце концов, я решил эту проблему.