Создание PHP API: проверка, с какого сервера поступает запрос API - PullRequest
11 голосов
/ 10 августа 2011

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

  1. API настроен на api.example.com.
  2. Пользователь, который хочет использоватьAPI регистрируется у нас, добавляет свой домен и получает ключ API.
  3. Пользователь API использует свой ключ API для шифрования данных своего запроса (через mcrypt) и отправляет его через cURLна api.example.com.
  4. Мой сервер проверяет, с какого домена поступил этот запрос API от , и сопоставляет этот домен с ключом API в базе данных.Если есть ключ API, API расшифровывает запрос с помощью mcrypt с этим ключом, а затем с помощью того же метода шифрует и отправляет результат.

Я застрял на шаге 4. Первоначально,Я планировал использовать HTTP_REFERER, чтобы проверить это, но поскольку cURL не отправляет его по умолчанию, и его можно легко подделать в коде на стороне пользователя (насколько я помню, CURLOPT_REFERER), я застрял здесь.* Есть ли способ узнать, из какого домена исходит этот запрос API?Я вижу, что это можно сделать с помощью некоторых популярных API, таких как reCAPTCHA.Проверка _SERVER ["REMOTE_HOST"] на самом деле не вариант из-за общих хостов (у них одинаковые IP-адреса), поэтому это не сможет предотвратить злоупотребления (которые в любом случае будут исходить в основном от общих серверов).* Есть ли такой способ проверить это?Спасибо!

Ответы [ 4 ]

7 голосов
/ 10 августа 2011

@ Шафи имеет хорошую идею, просто нужно немного подправить. Мы фокусируемся на видимой части вызова API, которая является ключом API. Это видно в URL и говорит API , кто запрашивает данные. Вместо того, чтобы пытаться не дать другим украсть этот ключ и выполнить свой собственный вызов cURL с доменом, из которого он его перехватил, мы можем просто добавить еще один ключ в микс, этот невидим для этих перехватчиков. Я не говорю о том, чтобы прекратить проверку того, откуда поступает запрос, это все еще хороший способ выкинуть недействительные запросы в самом начале сценария, но с помощью второго ключа вы гарантируете, что только тот, кто запрашивает данные, действительно знает, как получить данные (вы доверяете им, чтобы они никому не передавались).

Итак, когда пользователь регистрируется на ключ, вы фактически назначаете ему два разных ключа.
API_KEY - Открытый ключ, который соединяет вас с вашим доменом. Система ищет домен и предоставленный ключ, чтобы найти следующий ключ.
MCRYPT_KEY - это ключ, который будет использоваться для фактического шифрования этих данных через Mcrypt. Так как это зашифрованные данные, только запросчик и сервер будут знать, что это такое. Ключ используется для шифрования данных и отправки зашифрованного ввода с вашим ключом API на сервер, который находит ключ, необходимый для расшифровки этого ввода, с помощью предоставленного ключа API и домена (и IP). Если они не зашифровали данные с помощью правильного ключа, то дешифрование с помощью правильного ключа вернет бессмысленность, а вызов json_decode() вернет NULL, что позволит сценарию просто вернуть ответ «invalid_input».

В конечном счете, с помощью этого метода, нам даже нужно проверить, откуда (домен / IP) поступает запрос? Использование этого метода действительно сводится к тому, что пользователи API не передают свою пару ключей API / MCRYPT другим пользователям, подобно тому, как не передают ваше имя пользователя / пароль. Тем не менее, любой веб-сайт может легко зарегистрироваться, чтобы получить собственную пару ключей и использовать API. Также следует отметить, что API не будет даже возвращать что-либо полезное для своего сервера, если только пользователь на своем конце не войдет в систему, используя правильные имя пользователя и пароль, поэтому его конец уже будет иметь эту информацию. Единственное, что на самом деле возвращает наш сервер - это его адрес электронной почты после успешной проверки пользователя. Сказав это, нужно ли нам вообще использовать cURL? Не могли бы мы просто использовать file_get_contents('http://api.example.com/{$API_KEY}/{$MCRYPT_DATA}')? Я понимаю, что задаю больше вопросов в своем ответе ...

3 голосов
/ 10 августа 2011

Как насчет введения второй переменной, например, скажем app id.Когда пользователь регистрирует свой домен, ассоциируйте этот идентификатор с доменом.Пользователь должен отправить app id с каждым запросом без шифрования вместе с зашифрованным вызовом API.Тогда вы можете найти app id получить app secret и попытаться расшифровать?

3 голосов
/ 10 августа 2011

Вы можете изменить, с какого ip-адреса поступил запрос, и вы часто можете выполнить ptr-поиск, чтобы получить доменное имя для этого ip-адреса, но, скорее всего, ip-адрес имеет более одного домена, и вы в итоге получаете неправильный,поэтому я рекомендую, чтобы клиент отправлял свое имя домена в запросе, может быть, с HTTP_REFERER, и что вы делаете проверку DNS, если этот домен указывает на запрашиваемый IP-адрес, но обратите внимание, что домен, например google.com, может указывать назатем один ip.(ip может быть поддельно подделан, но с некоторыми хорошими навыками взлома, но это, насколько я знаю)

2 голосов
/ 10 августа 2011

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

Плюс, что если кто-то решит внедрить настольное приложение с использованием вашего API? Разумеется, они не будут требовать от своих пользователей отправлять им свои IP-адреса, чтобы они могли вносить их в белый список?

Кроме того, вы можете комбинировать ограничение скорости / ограничения запросов и ограничение скорости на основе количества запросов, например, как Verizon ограничивает скорость своей сети 3G, если вы передаете определенный объем данных.

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