Как различить внутренний и внешний запрос REST API? - PullRequest
0 голосов
/ 02 февраля 2019

На сервере, есть ли какой-нибудь способ провести различие между внутренним и внешним запросом API REST?

Почему?

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

Сводка

Мое определение внутреннего может быть неправильным.В данном случае «внутренний» означает запрос, сделанный из запроса XHTTP из того же домена, что и страница, обрабатывающая запрос.

Внешним вызовом может быть пользователь, создающий запрос Curl из другого домена.

Например:

http.service.ts

ВНУТРЕННИЙ УГЛОВОЙ ЗАПРОС 6


fetchLogin(formData: any): Observable<any> {
    let req = null;
    let headers = null;
    headers = {
      reportProgress: false,
      headers: new HttpHeaders({
        'email': formData['email'],
        'password': formData['password']
      })
    };
    req = new HttpRequest('POST', this.restApiUrl + this.restApiUrlEndpoint + '/oauth/', '', headers);
    return this.http.request(req)
    .map( (data) => {
      return 'body' in data ? data['body'] : null;
    })
    .pipe(
      catchError(this.handleError)
    );
  }

шаблон.cfm

ВНЕШНИЙ ЗАПРОС ХОЛОДНОЙ ФУЗИИ


<cfset httpUrl = request.restApiUrl & request.restApiUrlEndpoint & "/oauth/">

<cfhttp url="#httpUrl#" method="post" result="result" timeout="30">
  <cfhttpparam type="header" name="email" value="foo@bar.com" />
  <cfhttpparam type="header" name="password" value="foo" />
</cfhttp>

Пожалуйста, поймите, что я упростил эти 2 фрагмента кода, чтобы все было понятно.

Когда запрос попадает на сервер, как я могу узнать, какой запрос поступил через XHTTP, а какой был отправлен через CFHTTP [Curl]?

Я использую Taffy.io REST API framework,Итак, вот упрощенный метод внутри CFC «ресурсы», который я мог бы использовать для обработки запроса:

resources / oauthMember.cfc

<cfcomponent extends="taffy.core.resource" taffy_uri="/oauth">

<cffunction name="post">
  <cfset var local = StructNew()>
  <cfset local.data['email'] = "">
  <cfset local.data['password'] = "">
  <cfset local.requestBody = getHttpRequestData().headers>
  <cftry>
    <cfset local.data['email'] = Trim(local.requestBody['email'])>
    <cfset local.data['password'] = Trim(local.requestBody['password'])>
    <cfcatch>
    </cfcatch>
  </cftry>
  ...processing code
  <cfreturn representationOf(local.data) />
</cffunction>

</cfcomponent>

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

Есть идеи?

Среда

Windows 2008R2 Lucee 4.5 IIS7 +

1 Ответ

0 голосов
/ 02 февраля 2019

Короче говоря, вы ничего не можете доверять поступающему запросу в общедоступных данных API REST.Все в содержимом / заголовках запроса может быть создано с помощью curl или пользовательской программы.Возможно, вы доверяете IP-адресу источника сокета, если ваш веб-сервер настроен соответствующим образом и имеет прямой доступ к адресу подключения источника из самого сокета.В настоящее время это редкий случай, поскольку обычно веб-серверы теперь расположены за балансировщиками нагрузки, межсетевыми экранами с туннелями NAT и т. Д. Но даже в этом случае IP-адрес источника, вероятно, может использоваться только для какого-либо белого списка.Более того, сервер, который имеет такой доступ сегодня, может потерять его завтра, когда вашему приложению может понадобиться балансировщик нагрузки для масштабирования.Также обратите внимание, что у пользователя могут быть HTTP-прокси на исходном пути.Таким образом, использование исходного IP в качестве критериев API выглядит плохой практикой.

Хорошей практикой является создание общедоступного API, инвариантного для вызывающей стороны.Вызовы API должны быть сконцентрированы на теле запроса REST и предоставленных заголовках, чтобы проверить их действительность, приемлемость и безопасность.Действительно, многие вызовы API должны выполняться в такой последовательности, как «вход в систему» ​​-> sessionToken -> «вызовы API с помощью sessionToken» -> «выход из системы с помощью sessionToken» (токен признан недействительным).В этом случае важные данные (идентификатор пользователя, роль, контекст безопасности и т. Д.) Хранятся на сервере, как-то связанном с sessionToken.Примечание: многие разработчики API не рекомендуют хранить sessionToken в cookie, поскольку это может упростить CSRF-атаки (если не предоставлены другие контрмеры).

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

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

Приватный API вы можете изменить в любой момент, и вы можете создать его в видетак, как вам удобно.Но если ваш сайт работает, любой может сканировать свой собственный трафик и создавать похожие запросы с помощью curl (или чего-то похожего).Вы можете, однако, сделать некоторые трюки, чтобы усложнить жизнь обидчику, например, выпустить какие-то токены страниц, рассчитанные на JavaScript, использовать кратковременные цепочки запросов и т. Д., Но это не устраняет угрозу полностью.Поэтому API не может передать то, что «никто не может создать такой запрос», если все данные для запроса могут быть получены со страницы и трафика законным пользователем.

Резюме: лучше иметь публичный API для клиентов и частный API для сайтасам и не смешивай их.

...