Android

HTTPS GET (SSL) with Android and self-signed server certificate

HTTPS GET (SSL) с Android и самозаверяющим сертификатом сервера

Я просмотрел различные сообщения о том, как получить что-либо через HTTPS на Android с сервера, который использует самозаверяющий сертификат. Однако, похоже, ни один из них не работает - все они не удаляют


javax.net.ssl.SSLException: сообщение о ненадежном сертификате сервера.


Невозможно изменить сервер, чтобы у него был доверенный сертификат, и также невозможно сделать так, чтобы сертификат сервера соответствовал IP-адресу сервера.

Обратите внимание, что у сервера не будет DNS-имени, у него будет только IP-адрес. Запрос GET выглядит примерно так:

 https://username:password@anyIPAddress/blabla/index.php?param=1&param2=3

Я полностью осознаю, что это решение подвержено атакам типа "человек посередине" и т.д.

Таким образом, решение должно игнорировать недостаток доверия к сертификату и несоответствие имени хоста.

Кто-нибудь знает код, который делает это, используя Java для Android?

Есть множество попыток объяснить это на javalang.ru и множество фрагментов кода, но они, похоже, не работают, и никто не предоставил ни одного блока кода, который решает эту проблему, насколько я могу видеть. Было бы интересно узнать, действительно ли кто-то решил эту проблему, или Android просто блокирует сертификаты, которым нет доверия.

Переведено автоматически
Ответ 1

Как вы правильно указали, есть две проблемы: а) сертификат не является надежным и б) имя в сертификате не совпадает с именем хоста.

ПРЕДУПРЕЖДЕНИЕ: для всех, кто еще приходит к этому ответу, это грязный, ужасный взлом, и вы не должны использовать его ни для чего важного. SSL / TLS без аутентификации хуже, чем вообще без шифрования - чтение и изменение ваших "зашифрованных" данных тривиально для злоумышленника, и вы даже не узнаете, что это происходит.

Все еще со мной? Я этого боялся...

a) решается путем создания пользовательского SSLContext, TrustManager которого принимает все, что угодно:

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[] {
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; }
}
}, null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());

и б) путем создания HostnameVerifier, который позволяет продолжить подключение, даже если сертификат не соответствует имени хоста:

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});

Оба должны произойти в самом начале вашего кода, прежде чем вы начнете возиться с HttpsURLConnections и так далее. Это работает как в Android, так и в обычной JRE. Наслаждайтесь.

Ответ 2

Я создал приложение, которое использует самозаверяющие сертификаты или доверяет всем сертификатам. Исходный код находится здесь и бесплатен для использования: P

Просто используйте HttpManager и создайте фабрику SSL, используя trust all one . Пример кода можно найти здесь.

Ответ 3

Если вы используете HttpsURLConnection, то попробуйте вызвать setHostnameVerifier его раньше connect() и передать ему HostnameVerifier который просто принимает независимо от достоверности.

Ответ 4

Вы можете сделать это тихо и безопасно: http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

java android ssl