Находки программиста
Решения конкретных задач программирования. Java, Android, JavaScript, Flex и прочее. Настройка софта под Linux, методики разработки и просто размышления.
среда, 27 мая 2015 г.
Https в Android: делаем правильно
To что я опишу ниже — не открытие и не тайна. Это есть даже в официальной документации. Проблема в том, что большинство программистов под Android (и я в том числе) пришли из других, более старых платформ, где проблемы с ssl решались иначе или не возникали вообще.
Например, если сертификат вашего сервера почему-то не в порядке (например он самоподписной), то решение отключить проверку сертификата напрашивается само собой. Такое себе «быстрое решение». В результате вроде бы https и все круто, но на публичном wifi ваш клиент рискует пообщаться по «защищенному» каналу с мошенником. Или, к примеру, вы подключаетесь по ip к своему серверу, а в сертификате прописан домен. Отключаем проверку домена? Давайте не будем спешить. Есть решение которое в «особых» случаях не только не снижает безопасность соединения вашего приложения с сервером но и повышает её до воистину параноидального уровня.
Совсем чуть-чуть теории.
Когда мы устанавливаем https-соединение с сервером, происходит такое себе «рукопожатие», в процессе которого клиент получает публичный ключ сервера. Этот ключ используется для шифрования трафика и для проверки подлинности сервера. Как убедиться что сервер действительно тот, за кого себя выдает? Сертификат, который он предоставляет клиентскому приложению должен быть заверен организацией, чей сертификат есть в системе Android как доверенный и в нём должно быть «зашито» имя домена, соответствующее тому, к которому мы обращаемся. Если мы отключаем проверку, то любой сертификат любого мошенника становится валидным, и вы отправляете ему данные. Он же может общаться с вами, проксируя ваши данные на ваш сервер, который ни о чем не подозревая, обслуживает его как нормального клиента.
Если у вас нет заверенного сертификата, вы можете сгенерировать его себе самостоятельно. Это бесплатно. Но после этого ваше приложение должно доверять этому сертификату «без опоры на авторитеты». Это можно сделать двумя способами: быстрым и правильным. Быстрый — отключить проверку. Правильный: «вшить» публичный ключ вашего сервера в клиентское приложение. Так вы сможете доверять соединению с вашим сервером, не доверяя больше никому, даже самым «супернадежным» сертификатам.
И практика.
Допустим, наш сервер telebank.ru. Он https, причем его сертификат заверен GeoTrust, поэтому мы все ему доверяем. Но допустим, мы хотим принимать его не потому что он заверен кем-то а потому, что он «вшит» в наше приложение. Тогда даже конец света не помешает нам установить защищенное соединение 😉
1. Получим свой публичный ключ:
Из того, что приехало в ответ берём строчки начиная с —BEGIN CERTIFICATE— и заканчивая —END CERTIFICATE—, и сохраняем их в файл, к примеру в telebank.ru.cer. Это и будет наш публичный ключ в base64 представлении.
2. Чтобы работать с ключом, сделаем ему хранилище с помощью BouncyCastle Provider. Скачать его можно, например тут. Скачиваем библиотеку, кладём её рядом с нашим файлом сертификата и выполняем:
И, собственно, наш класс, расширяющий стандартный DefaultHttpClient:
7 комментариев:
Конгениальное решение! Особенно когда завтра у сертификата telebank.ru кончится срок или его перевыпустят по любой другой причине — ваше супергениальное решение немедленно перестанет работать. И пока вас не задолбают благодарные пользователи и вы не перевошьёте другой сертификат — не начнёт. С совершенно валидным сетификатом, подписанным доверенной организацией.
Ваша задача решается куда проще — вы смотрите, доверен ли сертификат и на какой домен он выдан. И неваши домены игнорите. Так вы и используете механизмы подписанных (доверенных) сертификатов, и не разрешаете своему 😉 приложению ходить налево.
Внимательно читая пост, можно заметить что решение предлагается как раз для «особых» случаев, когда сертификат нельзя или нет резона использовать традиционным способом.
Например, ваш сервер используется только как точка доступа для запросов мобильного клиента и не обслуживает браузер в принципе. Зачем покупать для него «совершенно валидный сетификат, подписанный доверенной организацией»?
На счет замены сертификата — этот минус описан, но по-моему замена сертификата раз в несколько лет не должна быть проблемой для мобильного приложения, которое штатно обновляется раз в 2-3 недели.
Ваше решение с проверкой домена — хорошее, но это решение другой задачи. Не пускать приложение «налево» в рамках описанного в посте метода скорее бонус, чем главная цель.
Источник
Android. GET и POST запросы к web серверу
5 сентября 2016 г. 3 Yehor Rykhnov 12682 android, java—>
Довольно часто приложению необходимо обмениваться информацией с сервером, для этого используется HTTP или HTTPS протокол. Рассмотрим простой пример запроса к серверу и получение ответа от него.
Запросы к web серверу нужно выполнять в отдельном потоке.
Подготовка
Установим в манифесте разрешение на работу с интернетом:
Работа с GET запросом
Для передачи спец символов (например: !»№;%?()) необходимо их преобразовать с помощью URLEncoder:
Работа с POST запросом
Если у вас есть вопросы или предложения по улучшению кода описанного в статье пишите в комментариях.
Я всегда открыт к конструктивному диалогу
Рекомендуемые
Комментарии
Для того, чтобы работал DefaultHttpClient — нужно установить бибилотеку apache.http. Для этого, в Android Studio:
1. Открываем Build->Edit Libraries and Dependencies->Dependencies.
2. Нажимаем на плюсик (+)
3. Выбираем Library Dependency
4. В поле поиска пишем org.apache.http и нажимаем «Enter» или жмем на кнопку поиска
Должно найти библиотеку org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2
5. Выбираем ее.
6. Жмем «Ok»
Если хотим тестить на локальном сервере — обращаемся к локальному хосту по ip. К хосту привязываем ip сетевой карты.
Источник
Какую библиотеку работы с HTTP в Android выбрать?
Представляю вашему вниманию перевод статьи «Which Android HTTP library to use?».
Для чего это вообще?
Немного истории
До Froyo HttpURLConnection имел некоторые не очень приятные баги. В частности, вызов close() у читаемого InputStream мог испортить пул соединений.
… большой размер их API мешает нам улучшать эту библиотеку без потери обратной совместимости. Команда Android не работает активно над Apache HTTP Client.
Apache HTTP client имеет мало багов на Eclair и Froyo, поэтому он является лучшим выбором для этих версий. А для Gingerbread и младше лучше подходит HttpURLConnection. Простота API и небольшой вес хорошо подходят для Android. Прозрачное сжатие и кэширование ответов помогают увеличить скорость и сохранить батарею. Новые приложения должны использовать HttpURLConnection.
Даже сегодня, если вы загляните в исходники Volley от Google (о ней я расскажу чуть попозже), вы сможете найти такое наследие:
Это классический пример фрагментации Android, которая заставляет страдать разработчиков. В 2013 году Square обратила внимание на эту проблему, когда выпускала OkHttp. OkHttp была создана для прямой работы с верхним уровнем сокетов Java, при этом не используя какие-либо дополнительные зависимости. Она поставляется в виде JAR-файла, так что разработчики могут использовать ее на любых устройствах с JVM (куда мы включаем, конечно, и Android). Для упрощения перехода на их библиотеку, Square имплементировали OkHttp используя интерфейсы HttpUrlConnection и Apache client.
OkHttp получила большое распространение и поддержку сообществом, и, в конце-концов, Google решили использовать версию 1.5 в Android 4.4 (KitKat). В июле 2015 Google официально признала AndroidHttpClient, основанный на Apache, устаревшим, вместе с выходом Android 5.1 (Lolipop).
Сегодня OkHttp поставляется со следующим огромным набором функций:
- Поддержка HTTP/2 и SPDY позволяет всем запросам, идущим к одному хосту, делиться сокетом
- Объединение запросов уменьшает время ожидания (если SPDY не доступен)
- Прозрачный GZIP позволяет уменьшить вес загружаемой информации
- Кэширование ответов позволяет избежать работу с сетью при повторных запросах.
- Поддержка как и синхронизированных блокирующих вызовов, так и асинхронных вызовов с обратным вызовом (callback)
Моя самая любимая часть OkHttp – как красиво и аккуратно можно работать с асинхронными запросами:
Это очень удобно, так как работа с сетью не должна быть в UI потоке. По-факту, начиная с Android 3.0 (Honeycomb, API 11), работа с сетью в отдельном потоке стала обязательной. Для того, чтобы воплотить что-то похожее с HtttpUrlConnection, вам потребуется построить большую (а может и монструозную) конструкцию с использованием AsyncTask или отдельного потока. Это будет еще более сложным, если вы захотите добавить отмену загрузки, объединение соединений и т.п.
Кстати, не осталась у обочины и HTTP библиотека от Google под названием Volley, которая предоставляет нам следующие бонусы:
- Автоматическое планирование сетевых запросов
- Множество параллельных сетевых соединений
- Прозрачное кэширование в памяти и на диске, в соответствии со стандартной кэш-согласованностью.
- Поддержка приоритизации запросов.
- Отмена API запросов. Вы можете отменить как один запрос, так и целый блок.
- Простота настройки, например, для повторов и отсрочек.
- Строгая очередность, которая делает легким корректное заполнение данными, полученными асинхронно из сети, интерфейса пользователя.
- Инструменты отладки и трассировки
Все, что ни есть в Volley, находится на вершине HttpUrlConnection. Если вы хотите получить JSON или изображение, то Volley имеет на это специальный абстракции, такие как ImageRequest и JsonObjectRequest, которые помогают вам в автоматическом режиме конвертировать полезную нагрузку HTTP. Так же достойно внимания то, что Volley использует жестко запрограммированный размер сетевого пула:
Когда OkHttp использует поток для каждого вызова с ThreadPoolExecutor с максимальным значением Integer.MAX_VALUE:
В результате, в большинстве случаев OkHttp будет действовать быстрее за счет использования бОльшего количества потоков. Если по каким-то причинам вы захотите использовать OkHttp вместе Volley, то есть реализация HttpStack, которая использует API запросов/ответов из OkHttp заместо HttpURLConnection.
HTTP клиенты продолжили развиваться для поддержки приложений с большим количеством картинок, особенно тех, кто поддерживает бесконечную прокрутку и трансформацию изображений. В то же время, REST API стал стандартом в индустрии, и каждый разработчик имел дело с такими типовыми задачами как сериализация в/из JSON и преобразование REST-вызовов в интерфейсы Java. Не прошло много времени, как появились библиотеки, решающие эти задачи:
- Retrofit – типобезопасный HTTP Android клиент для взаимодействия с REST-интерфейсами
- Picasso – мощная библиотека для загрузки и кэширования изображений под Android
Retrofit предоставляет некий мост между Java кодом и REST-интерфейсом. Он позволяет быстро включить в ваш проект HTTP API интерфейсы, и генерирует самодокументирующуюся реализацию.
В дополнение ко всему, Retrofit поддерживает конвертацию в JSON, XML, протокол буферов (protocol buffers).
Picasso, с другой стороны, предоставляет HTTP библиотеку, ориентированную на работу с изображениями. Например, вы можете загрузить изображение в свой View с помощью одной строчки:
Picasso и Retrofi настроены так, чтобы использовать OkHttpClient как стандартный HTTP клиент. Однако, если хотите, вы можете указать клиентом HttpURLConnection.
Glide – что-то похожее на Picasso. Он предоставляет некоторые дополнительные функции, такие как GIF-анимация, генерация миниатюрных эскизов изображения и неподвижные видео. Полное сравнение можно найти здесь.
Facebook недавно открыли общественности исходный код библиотеки Fresco, которую они используют в своем мобильном приложении. Одна из ключевых функций, которая выделяет ее, — кастомная стратегия выделения памяти для bitmap’ов, чтобы избежать работы долгого GC (сборщик мусора). Fresco выделяет память в регионе, который называется ashmem. Используются некие трюки, чтобы иметь доступ к этому региону памяти доступ как из части, написанной на C++, так и из части на Java. Чтобы уменьшить потребление CPU и данных из сети, эта библиотека использует 3 уровня кэша: 2 в ОЗУ, третий во внутреннем хранилище.
Я нашел необходимым показать отношения между библиотеками на одной схеме. Как вы можете увидеть, HTTP всегда остается внизу у высокоуровневых библиотек. Вы можете выбирать между простым HttpUrlConnection или последним OkHttpClient. Мы используем эту совместимость при разработке PacketZoom Android SDK, о котором мы поговорим в следующем посте.
Недавно мы сравнивали между собой HTTP библиотеки по производительности, но эта тема заслужила отдельного рассмотрения. Мы надеемся, что этот обзор дал вам основные идеи о плюсах и минусах каждой библиотеки, и мы помогли вам сделать правильный выбор. Следите за выходом более интересных постов о сетевой работе в Android от нас.
Источник