2013-03-12 3 views
12

Общим вариантом использования WebAPI было бы отображать представления оболочки с помощью MVC-контроллеров, которые содержат javascript, который затем попадает в ваш API для доступа к данным.Как сделать действия WebAPI доступными только из моего приложения?

Но предположим, что у вас есть дорогостоящие операции API, и вы не хотите, чтобы люди дистанционно обращались к этим конечным точкам - вы хотите, чтобы ваши просмотры MVC, предоставленные вашим приложением, получили доступ к ним. Как вы могли защитить их?

В этом случае Request.IsLocal не работает, потому что javascript вызывает его из браузера клиента на своей машине. Даже если это действительно сработало, вам нужно копать, чтобы получить реальный HttpContext, чтобы найти это свойство - и это решение не будет работать в самообслуживании WebAPI.

Для конечных точек API, для которых требуется действительный IPrincipal, вы можете защитить их с помощью атрибута [Authorize]. Но как насчет конечных точек API, к которым вы хотите, чтобы ваше приложение было доступно для анонимных пользователей?

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

ответ

2

Если ваш сайт MVC использует аутентификацию, вы можете включить проверку подлинности на основе форм для своих методов веб-API. Вы можете написать собственный атрибут [Authorize], который будет проверять наличие куки-файла проверки подлинности форм, который будет отправлен из вызова AJAX, и если он содержит конструкцию принципала.

Другим возможным решением является защита вашего API с помощью tokens, который является более RESTful. Идея здесь заключается в том, что когда пользователь аутентифицируется на вашем веб-сайте MVC, вы можете сгенерировать и передать токен представлению, которое будет использоваться при отправке запроса AJAX в веб-API, который, в свою очередь, проверяет правильность токена и его подпись.

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

+0

Что делать, если я хочу, чтобы действие было доступно для анонимных пользователей? – danludwig

+0

@ danludwig - ограничение доступа к дорогому ресурсу и предоставление неограниченного доступа к нему противоречивые требования. Вы должны решить. –

+0

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

2

Прежде чем вы начнете обсуждать «что вы пробовали», вот что я пробовал. Оно работает. Просто не уверен, есть ли лучший способ.

  1. Создание фильтра действий MVC и добавить его в качестве глобального фильтра во время Application_Start.

  2. Создайте фильтр действий Http (WebAPI) и используйте его для действий, которые должны отклонять удаленные запросы.

Глобальный фильтр MVC делает это:

  1. выглядит для конкретного печенья в запросе. Если файл cookie существует, его значение расшифровывается. Дешифрованное значение должно быть строковым представлением DateTime, поэтому используйте DateTime.TryParse, чтобы получить его. Если значение правильно разобрано на DateTime и что DateTime составляет менее одного дня, остановитесь здесь и ничего не делайте.

  2. Если cookie не существует или не может быть расшифрован/проанализирован или старше одного дня, напишите новый файл cookie в браузере. Используйте текущий DateTime.UtcNow.ToString() как значение, зашифруйте его и напишите его HttpOnly = false.

WebAPI фильтр делает это:

  1. выглядит для конкретного печенья в запросе. Если файл cookie существует, расшифруйте его значение и попытайтесь проанализировать его как DateTime.

  2. Если значение является действительным DateTime и составляет менее 2 дней, ОСТАНОВИТЕ ЗДЕСЬ и ничего не делайте.

  3. В противном случае бросить запрещенное исключение 403.

Несколько заметок о моей текущей реализации этого. Прежде всего, я использую шифрование AES с общим секретом и солью. Общий секрет хранится как appSetting в web.config. Для соли я включил анонимную идентификацию и использовал Request.AnonymousID в качестве соли. Я не совсем люблю соль, потому что это сложно сделать в контроллере WebAPI, но не невозможно, если это не самообслуживание.

+2

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

+0

@DarinDimitrov, это своего рода правда. Обратите внимание, что это не для защиты всего API, а только для некоторых конечных точек, для которых не требуется «IPrincipal». Также пользователю необходимо будет захватить 2 файла cookie, включая .ASPXANONYMOUS, так как он используется как соль шифрования. Но это усложняет ситуацию. Я прочитаю вашу ссылку на токены, спасибо за это. – danludwig

+1

Для справки это называется повторной атакой, то есть злоумышленник может успешно отправить запрос. Методология @ danludwig защищает несколько, делая срок действия запроса «истекающим» после дня. Однако, день еще долгое время; Более типичным является 15 минут. Вы также, как правило, захотите также зашифровать тело запроса (т. Е. Опубликованные поля). Это предотвращает модификацию данных, что делает воспроизведение бесполезным для большинства функций. –

Смежные вопросы