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

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

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

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

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

 https://username:[email protected]/blabla/index.php?param=1&param2=3

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

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

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

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

 Adrian Spinei31 окт. 2010 г., 17:10
Ни один из них не работал для меня (усугубляется ошибка Thawte, а также увидетьbit.ly/bypAk2). В конце концов я получил это исправить сstackoverflow.com/questions/1217141/... а такжеstackoverflow.com/questions/2899079/...

Ответы на вопрос(7)

 Lars D25 сент. 2010 г., 12:21
Я уже попробовал два фрагмента исходного кода, с которыми вы связались, но оба сообщают, что сертификат сервера не является доверенным, кажется, что он просто не работает.
 Colin Hebert25 сент. 2010 г., 12:40
На мой взгляд, лучший способ справиться с этим - переписать свойSSLSocketFactory если вы не хотите использовать хранилище ключей. Этот урок подробно объясняет, как это сделать:mobile.synyx.de/2010/06/...
 Lars D25 сент. 2010 г., 12:24
Я также попробовал часть кода в потоке "HTTPS-соединение Android" - с тем же результатом. Что меня беспокоит, так это то, что все те, кто пытается помочь, не предоставляют ни одного работающего фрагмента кода, и, если я объединю предоставленные ими фрагменты кода, это не сработает.
 Lars D25 сент. 2010 г., 13:56
Это должно быть однострочно в обычной среде, интересно, почему ни у кого нет кода для вставки.
 Lars D25 сент. 2010 г., 14:43
Хорошие инструменты программирования всегда облегчают тестирование вашего кода, и никто не хочет тратить время на установку доверенного сертификата для простого теста, который не связан с производством и не нуждается в безопасности. Точно так же, как мы можем использовать telnet для тестирования SMTP или HTTP-сервера, необходимо легко загрузить что-либо с HTTPS-сервера, отключив безопасность.
 Colin Hebert25 сент. 2010 г., 15:13
Что касается разработки, я всегда либо вручную добавлял самоподписанный сертификат, либо создавал свой собственный CA. Это не так сложно создать, и это действительно помогает увидеть, как это будет работать на производстве. В любом случае, вы читали ссылку в моем предыдущем комментарии? Это позволяет вам легко использовать хранилище ключей.
 Colin Hebert25 сент. 2010 г., 14:16
Как вы сказали, SSL не может принимать любой сертификат. Поэтому, очевидно, нет простого способа справиться с этим. Как я уже сказал выше, лучший способ сделать это - использовать метод хранилища ключей. В своем блоге есть интересная статья от Боба Ли, посвященная этой конкретной теме. Он использовал надувной замок для обработки части хранилища ключей:blog.crazybob.org/2010/02/...
 Lars D25 сент. 2010 г., 12:26
Добавление сертификата в хранилище ключей является одним из обходных путей, но это утомительный процесс, потому что для этого потребуется, чтобы клиент знал конфигурацию сервера, а это нежелательное предположение.
 Lars D26 сент. 2010 г., 13:37
В моем случае сертификат сервера не обязательно известен во время установки приложения Android. То, что никто, кажется, не имеет исходного кода для этого, начинает внушать мне, что Android не способен на это.

Нашел хороший учебникhttp://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/ и это действительно не так сложно реализовать.

Также учебник, рекомендованный Maciek, очень хорош.

Я протестировал его, и он работает в моем приложении без проблем.

setHostnameVerifier на это раньшеconnect()и передать егоHostnameVerifier который просто принимает независимо от правдивости.

 Lars D21 сент. 2010 г., 22:22
Я пробовал это, но это не удаляет сообщение об ошибке.
 user20742122 сент. 2010 г., 09:47
Это работает для меня, но по общему признанию в Java. Вы уверены, что звонили, прежде чем делать какие-либо операции ввода-вывода с подключением?
 Yuliy22 сент. 2010 г., 17:48
Что произойдет, если вы попытаетесь подключиться к тому же серверу, используя Java на устройстве без Android?
 Lars D25 сент. 2010 г., 09:14
Юлий, если у вас есть какой-то код, который, как вы знаете, работает на Java в целом, вы можете опубликовать его, и я попробую его. Но, пожалуйста, отправьте полный код.
 Yuliy22 сент. 2010 г., 21:34
Ларс, прошу попытаться определить, является ли тот факт, что он на андроиде красной селедкой. Вот что будет делать попытка установить SSL-соединение с настольного Java-клиента.
 Lars D22 сент. 2010 г., 21:27
Юлий, ваш вопрос имел бы смысл только в том случае, если бы у меня был один кусок кода, который не работает, и я попытался исправить этот кусок кода. Но я пробовал много разных кусков кода, из stackoverflow.com и других мест. Некоторые из них, вероятно, работают за пределами Android, а некоторые нет. Это не поможет мне. Цель состоит в том, чтобы найти полный фрагмент кода для Android, который, как известно, работает.
 Lars D22 сент. 2010 г., 16:11
Я пробовал много разных фрагментов кода, которые заменяют верификатор имени хоста и делают разные виды игнорирования SSL-сертификатов, но сообщение об ошибке сертификата продолжает поступать, независимо от того, какой фрагмент кода я копирую. Мне не имеет смысла публиковать конкретный исходный код, потому что я пробовал несколько разных решений - то, что я хотел бы видеть, это то, что работает на Android. Кто-то должен был решить проблему раньше, и там должна быть возможность скопировать и вставить некоторый исходный код ...

а) сертификат не является доверенным, и б) имя в сертификате не соответствует имени хоста.

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

Все еще со мной? Я так боялся ...

а) решается путем создания собственного 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. Наслаждаться.

 n j12 февр. 2015 г., 13:08
Спасибо, это работает для меня! :)
 w.donahue05 нояб. 2010 г., 04:59
Я попробовал это, и я могу подтвердить, что это работает.
 Chathura Wijesinghe27 нояб. 2013 г., 05:21
отличная работа спасибо
 plainjimbo17 сент. 2011 г., 01:52
Я буду второй, у меня тоже работает
 BurninLeo19 июн. 2012 г., 15:27
В вопросе уже упоминались вопросы безопасности. Однако, когда вы пробираетесь через хранилище ключей и сортируете сертификаты и - спустя несколько часов - все еще возникают проблемы, потому что «GlobalTrust CA, Inc.» это не то же самое, что "GlobalTrust CA Inc." (без запятой) вы начинаете думать, если данные вообще разумны - и я очень благодарен за фрагмент кода, который «отключает безопасность». По крайней мере, для прототипа ...

которое использует самоподписанный сертификат 4 месяца назад, вот код, который, я надеюсь, поможет:https://bitbucket.org/momo0002/tlsdemo.git

которое использует самоподписанные или доверяет всем сертификатам. Источник здесь:http://code.google.com/p/meneameandroid/source/browse/#svn/trunk/src/com/dcg/auth и бесплатно использовать: P

Просто используйте HttpManager и создайте фабрику SSL, используя все доверие:http://code.google.com/p/meneameandroid/source/browse/trunk/src/com/dcg/util/HttpManager.java

РЕДАКТИРОВАТЬ: Ссылки обновлены

 uLYsseus21 февр. 2014 г., 16:56
SSLPeerUnverifiedException: нет сертификата однорангового узла
 Devunwired19 дек. 2010 г., 23:35
Я так счастлив, я мог плакать. Этот код был первым решением, которое сработало после долгих поисков. Спасибо x1000 за открытый исходный код!
 Moss25 нояб. 2010 г., 11:43
@ Lars D У тебя сработало?
 Moss14 нояб. 2010 г., 16:25
Я только что обновил ссылки!
 Evan R.14 сент. 2012 г., 21:33
не могу сделать эту работу. Я изменил SSLSocketFactory в HttpManager на «TrustAllSSLSocketFactory», но продолжаю получать «java.security.cert.certpathvalidatorexception: доверительный якорь для пути сертификации не найден. Вернуть недопустимый сеанс с недопустимым набором шифров SSL_NULL_WITH_NULL_NULL
 Lars D13 нояб. 2010 г., 09:48
Вторая ссылка не работает.
 Tim Büthe09 нояб. 2010 г., 13:39
Как говорит @Lars D, другие решения на SO не работают, но это работает, большое спасибо!

Ваш ответ на вопрос