обеспечение REST API, доступного из Android - PullRequest
30 голосов
/ 03 октября 2011

Мы создаем игру для Android, которая нуждается в доступе к веб-сервисам - поэтому мы написали RESTful API на PHP, который работает на нашем собственном сервере.Что API предлагает: создание пользователя, вход в систему, загрузка игр, получение списка игр, отправка счета ... и т. Д. Теперь я думаю, если какой-нибудь опытный пользователь получит формат URL API - он / она сможет очистить систему разными способами:

  • Создайте скрипт и запустите его для создания автоматических пользователей - я думаю, что я могу предотвратить это с помощью CAPTCHA или чего-то другогокак это.Но опять же, капча будет раздражать игроков.
  • Злоумышленник входит в систему с помощью своего браузера, загружает игру и затем отправляет счет по своему желанию - и все это посредством вызова API, просто набрав его в своем браузере.Я предполагаю, что злонамеренный пользователь каким-то образом знает URL-адреса API для вызова - путем сниффинга, когда приложение отправляет HTTP-запросы.
  • Мне нужно убедиться, что запросы поступают только с устройства Android, на котором установлена ​​игра.(Игра будет бесплатной)

Теперь, как я могу предотвратить такие злоупотребления?

Ответы [ 5 ]

32 голосов
/ 03 октября 2011

Я думаю, вы никогда не сможете скрыть URL-адреса, вызываемые приложением (если я использую телефон Android с root-правами, я должен быть в состоянии шпионить за всем сетевым трафиком)

Но вашреальная проблема заключается в том, что вам нужно как-то аутентифицировать ваш API.

Один из способов - реализовать OAUTH, но, возможно, это будет излишним.

Если вам нужен простой механизм, какоб этом;

  1. создайте секретный ключ
  2. создайте запрос API (например, https://my.example.com/users/23?fields=name,email)
  3. хешируйте этот путь запроса + плюс ваш секретный ключ (например,md5 (url + secret_key) == "a3c2fe167")
  4. добавить этот хеш к вашему запросу (теперь это https: // .....? fields = name, email & hash = a3c2fe167 )
  5. на конце API, сделайте то же преобразование (удалите хеш-параметр)
  6. проверьте md5 URL и секретного ключа

Покапоскольку секрет остается секретным, никто не может подделать ваши запросы.

Пример (в псевдокоде):

Сторона Android:

SECRET_KEY = "abc123"

def call_api_with_secret(url, params)
  # create the hash to sign the request
  hash = MD5.hash(SECRET_KEY, url, params)

  # call the api with the added hash
  call_api(url+"&hash=#{hash}", params)
end

Сторона сервера:

SECRET_KEY = "abc123"

def receive_from_api(url, params)
  # retrieve the hash
  url_without_hash, received_hash = retrieve_and_remove_hash(url)

  # check the hash
  expected_hash = MD5.hash(SECRET_KEY, url_without_hash, params)

  if (expected_hash != received_hash)
    raise our exception!
  end

  # now do the usual stuff
end
9 голосов
/ 03 октября 2011

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

Вопрос в том, стоит ли взламывать ваше приложение?Такие схемы, как iTunes, DVD или Sony PS3, очевидно, стоили усилий.Подход безвестности может сработать, если никто не способен взломать заботы.Только не обманывайте себя тем, что это невозможно.

Поскольку вы не можете доверять устройству или приложению, вы должны доверять пользователю.Чтобы доверять пользователю, вам необходима система идентификации и авторизации пользователя.В основном логин для вашего приложения.Вместо этого вы используете собственную систему идентификации (войдите с электронными письмами с подтверждением и т. Д.), Используйте стороннюю систему: OpenID (учетные записи Google) или OAuth (Facebook, Twitter).В случае facebook используйте схему аутентификации на стороне сервера.

Что я буду делать:

  1. Разрешить пользователям свободно играть в игру, пока они не захотят «сохранить» результаты насервер.
  2. Перед сохранением своих результатов попросите их войти в систему вышеупомянутым способом.
  3. Используйте HTTPS для отправки данных на ваш сервер.Купите ssl-сертификат в доверенном CA, чтобы вам не приходилось иметь дело с самозаверяющими сертификатами.
3 голосов
/ 03 октября 2011

Вы упомянули пользователей, подделывающих высокие баллы.Это все еще может произойти, если ваши пользователи аутентифицированы.Когда игра загружает высокие баллы, вы можете захотеть, чтобы она также загружала доказательство счета.Например, счет 20100 из 103 разбитых жуков, пролетел 1200 миль, достиг 3 уровня и съел 2 вишни.Это ни в коем случае не идеально, но будет охватывать низко висящие фрукты.

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

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

1 голос
/ 20 сентября 2014

Следуйте этим рекомендациям от команды Android, чтобы обезопасить свой бэкэнд, используя токены Oauth, предоставляемые через API Google.

1 голос
/ 03 октября 2011

Если вы действительно хотите защитить соединение, вам придется использовать криптографию с открытым ключом, например, RSA. Устройство зашифрует информацию для входа в систему с помощью открытого ключа, а на стороне сервера вам придется расшифровать с помощью личного ключа. После входа в систему сервер отправит токен / ключ шифрования (ответом будет зашифрованный JSON или что-то еще), и устройство сохранит его. С тех пор, пока сеанс не истек, устройство будет отправлять всю информацию, зашифрованную с использованием этого токена. Для этого запроса вы не должны использовать RSA, потому что это займет больше времени. Вы можете использовать AES256 (это популярное шифрование с закрытым ключом) с этим ключом шифрования, полученным с сервера, для шифрования ваших запросов.

Ради простоты вы можете вообще отказаться от RSA (если вы не отправляете платежную информацию) и сделать все, используя AES256 с закрытым ключом. Шаги должны быть -

  • Зашифровывать каждый исходящий запрос закрытым ключом.
  • Преобразовать зашифрованную строку в строку base 64.
  • URL кодирует строку в кодировке Base 64.
  • Отправь это.

На стороне сервера

  • У декодирования base 64
  • Расшифровать с помощью закрытого ключа.

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

Для отправки ответов сделайте то же самое.

Android SDK должен иметь методы для шифрования с кодировкой AES256 и Base 64.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...