Статьи

О работе с веб-сервисами

В этой статье рассматриваются протоколы веб-служб, распространенные форматы обмена данными и передовые практики. Если вы заинтересованы в создании эффективных мобильных приложений, которые подключаются к сети, читайте дальше!


Выбор правильного протокола и формата обмена данными для передачи данных между вашим мобильным приложением и сетью является одним из наиболее важных решений, которые необходимо принять в процессе разработки. Наиболее распространенными и широко используемыми протоколами являются REST , XML-RPC и SOAP .

Все эти протоколы передают данные по протоколу HTTP. Протоколы XML-RPC и SOAP основаны на XML , в то время как службы REST могут полагаться на разные форматы данных, наиболее распространенными из которых являются XML и JSON . В частности, SOAP широко ценится и принимается корпоративными приложениями, поскольку он строго соблюдает модели данных и описывает общедоступные интерфейсы через WSDL , что позволяет некоторым инструментам разработки (таким как Microsoft Visual Studio для .NET) автоматически настраивать объекты и методы для использования. сервисы, просто добавив ссылку на сервис WSDL в проект.

Однако XML по своей конструкции менее эффективен, чем JSON, при работе в сценарии с ограниченной пропускной способностью сети, таком как разработка мобильных приложений. Мобильные сети передачи данных (WWAN), как правило, менее надежны, чем проводные (LAN) или беспроводные (WLAN) сети, потому что клиенты в движении могут легко выпадать из зон покрытия. Кроме того, некоторые пользователи не подписываются на «плоские» тарифные планы и фактически оплачиваются сетевым трафиком.

Поэтому при разработке для мобильных устройств вы всегда должны выбирать простоту и сокращение трафика.

Давайте сравним простой XML с JSON с примером ответа:

XML

1
2
3
<ServiceResponse>
    <ReturnValue>Hello, device!</ReturnValue>
</ServiceResponse>

JSON

1
2
3
{
    returnValue: «Hello, device!»
}

Как видите, JSON несет меньшую полезную нагрузку, потому что ему просто нужно обернуть свои данные скобками (фигурные для объектов, квадрат для массивов) и кавычками, в то время как XML нужен полный корневой узел и открывающие-закрывающие теги для каждого элемента или группы. Сохранение этих тегов может значительно сократить полезную нагрузку ответа, и чем больше данных вы передаете, тем больше будет «заполнение» полезной нагрузки с помощью XML.

Более того, SOAP и XML-RPC требуют более сложных структур данных XML (таких как «конверт» SOAP), добавляя дополнительный вес полезной нагрузке.

По этой причине я рекомендую выбрать JSON для формата обмена данными вашего приложения и REST для протокола передачи, если только XML, SOAP или XML-RPC явно не требуются для ваших нужд. Если вам необходимо применить модель данных, вы можете добиться этого и с помощью JSON, используя схему JSON или WSDL 2.0 .

Для ссылок и дальнейшего чтения о обсуждаемых протоколах и форматах данных, проверьте следующее:


Поскольку большинство веб-служб работают в общедоступных сетях, защита данных, которыми будут обмениваться службы и приложение, является одной из наиболее важных проблем, которые необходимо решить. Многие веб-службы предоставляют удаленную функциональность аутентифицированным пользователям, поэтому личные данные пользователя и учетные данные для аутентификации также необходимо передавать по сети.

Личные данные, данные учетной записи и учетные данные никогда не должны передаваться в виде открытого текста по общедоступной сети, поэтому это означает, что ваши веб-службы и приложения должны использовать криптографию. Хорошей новостью является то, что большинство распространенных протоколов транспортируют данные по HTTP, поэтому вы можете положиться на хорошо известный, надежный и надежный протокол HTTP SSL / TLS (HTTPS), который широко поддерживается как на стороне сервера, так и на стороне клиента.

Включить SSL на обычных веб-серверах довольно просто (есть много полезных ресурсов для Apache , IIS и Nginx ). Все, что вам нужно сделать, это купить сертификат SSL и установить его на своем сервере. В худшем случае вы также можете выдать самозаверяющий сертификат , который предоставит вам бесплатное шифрование, но я бы не рекомендовал это делать. Некоторые центры сертификации выпускают недорогие сертификаты , а преимущества, которые вы получаете от работы с доверенным, подписанным сертификатом, стоят дополнительных затрат (т. Е. Предотвращение атак «человек посередине» с использованием PKI ). Использование самозаверяющих сертификатов также может потребовать дополнительного кодирования или даже «хаков» для конкретных приложений, поскольку некоторые сетевые библиотеки будут отказывать в ненадежных HTTPS-соединениях (ознакомьтесь с этими статьями об Android, # 1 и # 2 и об iOS ).

Включение SSL на стороне клиента не представляет никакой сложности: обычные языки программирования обычно имеют классы и библиотеки HTTP, которые обеспечивают собственную поддержку HTTP-SSL и будут «автоматически» заботиться о шифровании, просто используя URL-адреса «https: //», а не «http». : // «URL для использования веб-сервисов.

Если вы выбираете недорогой SSL-сертификат, просто убедитесь, что устройства и операционные системы, для которых вы хотите разработать, имеют корневой сертификат CA эмитента, встроенный в готовый комплект, иначе они не будут доверять сертификату.

Вы никогда не должны просить пользователей патчить, изменять или взламывать свои системы для запуска ваших приложений, и если вы это сделаете, не ожидайте, что многие из них будут соответствовать.

Транзакции веб-сервисов должны быть атомарными , функционально совместимыми и масштабируемыми , поэтому веб-сервисы обычно не имеют состояния (посмотрите это интересное обсуждение значения «соединений без состояния»).

Многие веб-сервисы предоставляют пользовательские функции и доступ к конфиденциальной информации. Естественно, для этого требуется аутентификация. Поскольку такие транзакции не сохраняют состояние, вам традиционно требовалось подписывать запросы с помощью пользовательского ключа, обеспечивая аутентификацию при каждом удаленном вызове метода. Даже при передаче данных по HTTPS учетные данные пользователя подвергаются наибольшему риску, когда они передаются по общедоступной сети. Шифрование иногда нарушается.

Эта дилемма очень полезна для аутентификации на основе токенов, такой как OAuth . При использовании аутентификации на основе токенов необходимо отправить учетные данные пользователя только один раз. Если пользователь успешно прошел аутентификацию, ему будут предоставлены токены, которые можно использовать для аутентификации последующих удаленных вызовов методов.

Срок действия токена распространяется на ограниченный срок службы и может быть отозван в любое время его эмитентом (т. Е. На стороне сервера). С помощью аутентификации на основе токенов вы также можете совместно использовать одни и те же учетные данные пользователя между различными приложениями и службами, при этом связанные службы / приложения никогда не будут знать реальных учетных данных пользователя. Кроме того, этот метод аутентификации надежно хранит локальный кеш учетных данных на устройстве пользователя, так что пользователь может быть «запомнен» и ему не нужно будет проходить аутентификацию каждый раз, когда он будет использовать приложение (ввод сложных паролей на портативных устройствах может быть реальным боль и может сильно повредить обзоры приложений).

OAuth — это самая распространенная основанная на токене фреймворковая аутентификация, которая была принята такими крупными игроками, как Google, Twitter, Facebook и так далее. Позволяя пользователям повторно использовать существующие учетные записи, пропуская надоедливые регистрационные формы и сохраняя контроль над доступом к своим личным данным, вы можете значительно увеличить свою базу пользователей.

Некоторые провайдеры OAuth требуют, чтобы их собственный SDK импортировался в ваши приложения для включения аутентификации, в противном случае существует множество готовых библиотек OAuth, которые вы можете подключить к своему приложению. Существуют также фреймворки, такие как oauth-php, для создания пользовательских OAuth-провайдеров.

Я бы предложил указатель в качестве клиентской библиотеки Android OAuth и oauthconsumer для iOS.

Все эти библиотеки содержат полезные примеры и просты в реализации. Тем не менее, создание источников указателей на вашем компьютере или импорт их в ваше приложение может быть немного болезненным, но на самом деле вам не нужно проходить через этот процесс. Вместо этого вы можете просто импортировать JAR-файлы в ваш проект, и вы должны быть настроены. На iOS это будет похоже на импорт статической библиотеки (* .a файл) в ваш проект.

Наиболее распространенным методом аутентификации для сервисов на основе SOAP является расширение SOAP, называемое HTTP Basic Authentication (иногда называемое дайджест-аутентификацией). Это стандартная, хорошо поддерживаемая процедура, которая интегрирована во все наиболее распространенные веб-серверы, такие как Apache , Nginx и IIS . Он основан на паре имя пользователя-пароль, которую необходимо отправить на сервер через заголовки HTTP.

Как правило, вам не нужно вручную реализовывать базовую аутентификацию в своих приложениях, поскольку она широко поддерживается и в самых распространенных языках программирования. Платформа .NET использует класс NetworkCredential для предоставления базовых и дайджест-учетных данных аутентификации для HTTP-запросов, PHP поддерживает их через cURL , а Java — через Authenticator .

Если вам нужно реализовать Basic Auth самостоятельно, вам просто нужно добавить этот заголовок к вашим запросам:

1
Basic username:password

Значения «username» и «password» должны быть в кодировке base64 .

Обратите внимание, что HTTP Basic Auth лучше всего использовать в сочетании с протоколом HTTPS , поскольку он передает учетные данные в виде открытого текста . Digest Auth немного безопаснее, потому что он на самом деле хэширует значение пароля, но в любом случае рекомендуется HTTPS, чтобы избежать атак хеш-брутфорс.

Более подробную информацию и технические характеристики по этому вопросу можно найти в памятке IETF RFC 2617 .

При выборе метода аутентификации или интеграции хорошо известных сервисов (таких как социальные сети) вы также должны учитывать встроенные библиотеки, встроенные во многие современные платформы, такие как iOS и Android. Это может сэкономить вам много времени и много строк кода.

Android предоставляет удобную платформу для централизации управления учетными записями пользователей, класс AccountManager . Официальное руководство для разработчиков Android содержит хорошую документацию для этого класса, а также несколько советов по интеграции OAuth 2 или написанию собственного «Типа пользовательской учетной записи» .

В iOS 6 Apple представила новую социальную платформу для интеграции основных сервисов, таких как Twitter , Facebook и Sina Weibo, на уровне операционной системы. Даже если вам не нужно интегрировать эти сервисы в ваше приложение, вы можете найти подходящий способ воспользоваться встроенными методами аутентификации через настройку.


При разработке приложений для мобильных устройств важно поддерживать максимально возможную нагрузку на данные. В этом разделе будут обсуждаться несколько стратегий для этого.

Сжатие ZIP может значительно уменьшить текст, а также вес двоичных данных и хорошо поддерживается на большинстве платформ, поэтому используйте его, если вам нужно передавать большие данные по мобильным сетям. Полезные библиотеки для управления файлами ZIP доступны для Android (например, Decompress ) и iOS ( например, Ziparchive ).

Если вам необходимо передавать потоковое аудио / видео в мобильные приложения, выберите продвинутые потоковые платформы, которые позволяют им масштабировать потоки в зависимости от производительности сети / устройства, например, протокол Apple HTTP Live Streaming (HLS). В противном случае предпочтение отдается отзывчивости, а не качеству медиа. Поиграйте с различными видео и аудио компрессорами и настройками, максимально оптимизируя. Вы также можете группировать устройства по видам (карманные компьютеры с небольшим экраном, широкоэкранные карманные компьютеры и планшеты) и предоставлять различный контент для каждого вида.

Многие мобильные устройства оснащены HD-дисплеями, но действительно ли HD-контент на маленьких экранах действительно стоит дополнительных накладных расходов? Будьте честны в отношении важности качества мультимедиа в ваших приложениях и постарайтесь найти наилучший баланс между качеством и весом.

Предположим, вам нужно написать приложение для чтения онлайн-газет. Прежде всего, вы всегда должны разрешать своим пользователям работать в автономном режиме, когда это возможно. Хотя некоторым приложениям всегда требуется активная сеть (например, службы обмена сообщениями), многие другие должны использовать сеть только для загрузки пакетов данных и кэширования их на устройстве .

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

При загрузке контента на устройства, которые монтируют внешнее хранилище (например, карты памяти), вы должны позволить пользователям выбирать, где хранить загруженный контент (то есть внутреннее или внешнее хранилище) или просто в любом случае предпочитать внешнее хранилище. Устройства начального уровня обычно имеют довольно небольшое внутреннее хранилище и могут стать нестабильными или медленными при заполнении внутреннего хранилища. Если ваши приложения занимают много места для хранения, они, вероятно, будут удалены, чтобы сэкономить место.

Давайте вернемся к примеру приложения для чтения. Каждая статья представляет собой отдельный фрагмент, и хотя статьи могут быть связаны друг с другом, нет причин, по которым вы не должны позволять пользователям начинать чтение статей, даже если дополнительный контент все еще загружается. Таким образом, упакуйте файлы каждой статьи (текст, изображения, вложения и мультимедиа) в отдельные ZIP-архивы и предоставьте приложению метод веб-службы для получения списка доступных статей . Пусть ваше приложение загружает ZIP-пакеты один за другим, а затем делает их доступными в приложении, как только каждый из них будет загружен, а другие загружаются в фоновом режиме. Это отличная производительность и улучшение пользовательского опыта по сравнению с ожиданием загрузки всей полезной нагрузки! Вы также можете позволить пользователям выбирать, какие пакеты они хотят загружать или нет (что позволяет им экономить место, время и трафик), и разрешать им удалять отдельные пакеты для экономии места на диске без удаления всего приложения.

Ниже приведен ответ от приложения демо-сервера, прилагаемого к этой статье:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
    apiversion: 1,
    status: 0,
    packages:
        [
            {
                file: «pack01_01_01.zip»,
                package: «pack01»,
                appversion: 1,
                revision: 1
            },
            {
                file: «pack01_02_01.zip»,
                package: «pack01»,
                appversion: 2,
                revision: 1
            },
            {
                file: «pack02_01_01.zip»,
                package: «pack02»,
                appversion: 1,
                revision: 1
            }
        ]
}

Имейте в виду, что ваше приложение и ранее выпущенный контент могут со временем развиваться.

Установите флажок «revision» для каждого пакета в методе list, это пригодится для выпуска обновлений, исправления ошибок в содержимом и реализации функций автообновления в ваших приложениях. Даже если вы в настоящее время не планируете внедрять автообновление, подумайте и в любом случае добавьте флаг ревизии в свой список для дальнейшей разработки.

Вы также должны включить флаг «app-version» в свой список пакетов. Если вы выпустите новую основную версию своего приложения, в которой внесены серьезные изменения в формате контента, это позволит вам предоставлять контент как для новых, так и для старых приложений через одну и ту же веб-службу.


При разработке приложений, основанных на услугах, следует также учитывать отказоустойчивость сети и устройства. Мобильные соединения для передачи данных, как правило, менее стабильны, чем кабельные, приложения могут быть удалены и переустановлены, а устройства могут быть потеряны, заменены более новыми или восстановлены на заводе. Пользователям должна быть предоставлена ​​возможность легко восстанавливать приложения и контент, а разработчики платформы предлагают несколько полезных готовых решений этих проблем.

Не забывайте всегда проверять состояние сети перед вызовом удаленных служб или тщательно обрабатывать ошибки сетевого ввода-вывода и надлежащим образом информировать своих пользователей, когда желаемая задача не может быть выполнена из-за отсутствия активного соединения для передачи данных. Если ваши приложения должны всегда «работать в сети», вы можете добавить в свои приложения сторожевой таймер, который постоянно следит за состоянием сети и запускает событие при каждом изменении. Вы также можете сообщить пользователям о возможных дополнительных расходах при передаче больших объемов данных через сети 3G или роуминга, а не через Wi-Fi.

На устройствах Android эту задачу можно выполнить с помощью ConnectivityManager и SCNetworkReachability на iOS (также проверьте предоставленный пример приложения ).

И Android, и iOS предоставляют полезные API для удаленного облачного резервного копирования данных пользовательских приложений, о которых вам следует помнить. Ознакомьтесь с документацией по API iCloud для iOS и документации по службе резервного копирования Android для Android. Вместе со встроенными службами резервного копирования вы также получаете хорошие функции защиты данных. Однако вы должны быть осторожны, чтобы не перегружать службы резервного копирования избыточными или ненужными резервными копиями.

Вы также можете реализовать настраиваемое удаленное резервное копирование данных в своих веб-службах, но я настоятельно рекомендую придерживаться стандартов и встроенных API-интерфейсов платформы. Они обычно экономят ваше время и активно поддерживаются разработчиками программного обеспечения платформы. Исправления ОС также, скорее всего, будут быстро установлены после выпуска.

Если вы доставляете платный контент с помощью биллинга в приложении в своем приложении, то предоставление пользователям возможности восстановить свои покупки после переустановки приложения и восстановления устройства является обязательным . К счастью, iOS и Android имеют встроенные API для обработки этих сценариев.

Когда ваши приложения в приложении с покупкой запускаются в первый раз (или в первый раз после переустановки), вы должны запустить процедуру проверки покупки-восстановления. И iOS, и Android предоставляют хорошую официальную документацию по этому вопросу.

При разработке для Android помните, что только «управляемые» элементы могут быть восстановлены в более позднее время, и они доступны только при единовременной покупке. Это подразумевает некоторые соображения, которые относятся и к разработке под iOS.

Предположим, вы разрабатываете ролевую игру и хотите, чтобы игроки покупали такие предметы, как зелья здоровья, через биллинг внутри приложения. Прежде всего, поскольку пользователи могут купить столько зелий, сколько захотят, они не могут быть «управляемыми» элементами, поэтому их транзакции покупки не хранятся постоянно. Кроме того, если пользователь покупает 20 зелий и использует 10, а затем удаляет и переустанавливает игру, восстановление покупок с помощью простой стандартной процедуры помещает 20 зелий обратно в инвентарь пользователя, 10 из которых являются непреднамеренным бесплатным подарком от разработчики.

Таким образом, вам может потребоваться реализовать собственные пользовательские веб-службы и методы приложения для обработки хранения и восстановления транзакций в сложных сценариях или пограничных случаях.


Сроки и бюджеты часто ограничивают вас и не позволяют вам следовать всем рекомендациям, описанным в этой статье. Но даже если вы вынуждены придерживаться небольшого подмножества функций, подумайте о будущем , потратьте некоторое время на хороший дизайн и упакуйте свои методы и классы в библиотеки, которые вы сможете использовать и расширять позже. Оставьте заглушки, когда почувствуете, что есть место для дальнейшего развития. Также попытайтесь обеспечить обратную совместимость при расширении и улучшении своих библиотек, чтобы можно было исправлять и более старые приложения.

Это пример заглушки:

01
02
03
04
05
06
07
08
09
10
11
public void sendData(Object data) {
         if (validate(data)) {
                 client.send(data);
         }
}
 
// Stub
public boolean validate(Object data) {
         // TODO — Implement data validation
         return true;
}

Если вы начинающий разработчик или никогда не разрабатывали сервисные приложения, вам следует начать с предоставленного примера приложения в качестве хорошего упражнения, чтобы улучшить свои знания и превратить его в реальное приложение, применяя все концепции, описанные в этой статье, один за другим. время. В качестве альтернативы, запустите новое приложение с нуля и интегрируйте его с существующим поставщиком услуг (Facebook, Twitter, Last.fm или Dropbox — хорошая отправная точка) по тому же графику.

Если вы уже разработали некоторые сервисные и сетевые приложения, вы можете просмотреть существующий код и улучшить его в соответствии с принципами, описанными выше, отслеживая каждое улучшение и влияние на производительность и скорость реагирования.

Не забудьте также ознакомиться со связанными ресурсами, так как они помогут вам глубже понять суть каждой проблемы, а также загрузить пример сервера и клиентских приложений, представленных в статье.