HTTPS GET (SSL) с Android и самозаверяющим сертификатом сервера
Я просмотрел различные сообщения о том, как получить что-то через HTTPS
на Android, с сервера, который использует самозаверяющий сертификат. Однако ни один из них, похоже, не работает - все они не удаляют
javax.net.ssl.SSLException: сообщение сертификата несертифицированного сервера.
Невозможно изменить сервер, чтобы иметь доверенный сертификат, а также не может сделать сертификат сервера соответствующим IP-адресу сервера.
Обратите внимание, что сервер не будет иметь DNS-имя, оно будет иметь только IP-адрес. Запрос GET выглядит примерно так:
https://username:[email protected]/blabla/index.php?param=1¶m2=3
Я полностью понимаю, что это решение подвержено атакам типа "человек-в-середине" и т.д.
Итак, решение должно игнорировать отсутствие доверия к сертификату и игнорировать несоответствие имени хоста.
Кто-нибудь знает код, который делает это, используя Java для Android?
Есть много попыток объяснить это на stackoverflow.com и множество фрагментов кода, но они, похоже, не работают, и никто не предоставил один блок кода, который решает это, насколько я вижу. Было бы интересно узнать, действительно ли кто-то решил это, или если Android просто блокирует сертификаты, которым не доверяют.
Ответы
Ответ 1
Я сделал приложение, которое использует самоподписанные или доверяет всем сертификатам. Источник находится здесь: http://code.google.com/p/meneameandroid/source/browse/#svn/trunk/src/com/dcg/auth и может свободно использоваться: P
Просто используйте HttpManager и создайте SSL factory, используя доверие всего: http://code.google.com/p/meneameandroid/source/browse/trunk/src/com/dcg/util/HttpManager.java
EDIT: обновленные ссылки
Ответ 2
Как вы правильно отметили, есть две проблемы: a) сертификат не доверен, и b) имя в сертификате не совпадает с именем хоста.
ПРЕДУПРЕЖДЕНИЕ: для любого другого, кто приходит к этому ответу, это грязный, ужасный взлом, и вы не должны использовать его для чего-либо, что имеет значение. 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());
и b), создав HostnameVerifier, который позволяет продолжить соединение, даже если сертификат не соответствует имени хоста:
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
Оба должны произойти прямо в начале вашего кода, прежде чем вы начнете возиться с HttpsURLConnections и так далее. Это работает как в Android, так и в обычной JRE. Наслаждайтесь.
Ответ 3
Если вы используете HttpsURLConnection, попробуйте позвонить setHostnameVerifier
на нем перед connect()
и передать ему HostnameVerifier
, который просто принимает независимо от правдоподобия.
Ответ 4
Вы можете сделать это спокойно: http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
Ответ 5
Если у вас есть доступ к устройствам, вы можете добавить сертификат в хранилище ключей. Подробнее читайте здесь.
С другой стороны, вы можете использовать этот метод, но я считаю это своего рода уродливым.
Ресурсы:
В той же теме:
Ответ 6
Если вы спросите меня, сделайте это безопасным способом.
Нашел хороший учебник http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/, и это действительно не так сложно реализовать.
Также рекомендуется учебник, рекомендованный Maciek.
Я тестировал его, и он работает в моем приложении без проблем.
Ответ 7
Я сделал приложение, которое использует самоподписанный сертификат 4 месяца назад, вот код, на который я надеюсь: https://bitbucket.org/momo0002/tlsdemo.git