Я работаю над проектом, который должен поддерживать уровень API до 16 и требует от меня сетевых вызовов динамических URL-адресов.Проблема, с которой я столкнулся, заключается в том, что серверу недавно пришлось обновить TLS до 1.2 для соответствия PCI, который по умолчанию отключен в Android API 16-19.Хотя включить это не сложно, я сталкиваюсь с проблемой сертификатов X509 только для этих уровней API.
Я провел немало исследований, и хотя все эти ссылки были полезны:
1) Как включить поддержку TLS 1.2 в приложении Android (работающем на Android 4.1JB)
2) Как использовать самозаверяющий сертификат для подключения к серверу Mqtt в Android (клиент Paho)?
3) SSLSocketFactory в java
4) Разрешение Java использовать ненадежный сертификат для соединения SSL / HTTPS
5) Не найдена привязка доверия для Android SSLСоединение
6) SSLHandshakeException: доверенная привязка для пути сертификации не найдена.Только для Android API <19 </a>
7) Доверие всем сертификатам с использованием HttpClient через HTTPS
Они не решают основную проблему, с которой я столкнулся:см. это исключение:
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:151)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:409)
at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
at com.android.okhttp.Connection.connect(Connection.java:107)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:110)
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
... 1 more
Когда я пытаюсь подключиться к URL-адресу, для которого требуется TLS1.2, например https://www.ssllabs.com/ssltest/viewMyClient.html.
По сути, это сводится к проблеме с TrustManager.
Вот 2 различных способа получить объект TrustManager (первый надежнее второго, так как второй доверяет всем сертификатам, что делает SSL спорным пунктом):
Первый метод:
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
Второй метод:
X509TrustManager trustManager = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
Затем они используются с этим кодом:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, new TrustManager[] { trustManager }, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
Если я использую первый TrustManager на уровнях API 20+,URL, указанный выше, будет работать нормально, и страница загрузится.Если я использую первый на уровнях API 16-19, он выдаст исключение, указанное выше.
Если я использую второй TrustManager на любом уровне API 16+, вызов будет работать, но это оставляет пробел в безопасности в моем приложении, потому что я теперь доверяю всем сертификатам и оставляю себя открытым для всех видов атак,
Еще одно замечание: хотя приведенный выше пример ошибки взят из библиотеки Volley, она все же возникает при использовании Retrofit с теми же результатами.
Поэтому мой вопрос: как мне использоватьX509TrustManager для работы с веб-сайтами, такими как Этот на уровнях API 16-19, как они делают на уровнях API 20 +?
Спасибо за ваше время.