Подтвердить что ты не робот

Как сделать действия WebAPI доступными только из моего приложения?

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

Глобальный фильтр MVC выполняет следующее:

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

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

Фильтр WebAPI выполняет следующее:

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

  • Если значение является действительным DateTime и составляет менее 2 дней, остановитесь здесь и ничего не делайте.

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

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