Фильтры ресурсов реализуют один из двух интерфейсов — IResourceFilter
или IAsyncResourceFilter
. Эти фильтры охватывают большую часть конвейера фильтров так как до фильтров этого типа выполняются тольно фильтры авторизации. Фильтры ресурсов полезны для сокращенного выполнения большей части конвейера. Например, фильтр кэширования может предотвратить выполнение действия контроллера, если в кэше обнаружено необходимое значение. Второе, не менее популярное использование фильтра ресурсов — добавление или анализ заголовков.
Пример фильтра ресурсов в ASP.NET Core MVC
Для примера, рассмотрим фильтр ресурсов для простейшей авторизации пользователя. Какой-либо серьезной практической значимости этот фильтр не имеет, так как в ASP.NET Core MVC можно довольно легко реализовать полноценную систему аутентификации и авторизации пользователей, но показывает смысл одного из использований фильтров ресурсов в ASP.NET Core MVC.
Создадим новое приложение ASP.NET Core MVC, добавим в проект новую папку Filters и в этой папке создадим файл со следующим фильтром ресурсов:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; namespace AspResourceFilters.Filters { [AttributeUsage(AttributeTargets.Method)] public class SimpleAuthorizeFilter : Attribute, IResourceFilter { private readonly string _login; private readonly string _password; public SimpleAuthorizeFilter(string login, string password) { _login = login; _password = password; } public void OnResourceExecuted(ResourceExecutedContext context) { // throw new NotImplementedException(); } public void OnResourceExecuting(ResourceExecutingContext context) { var request = context.HttpContext.Request; if ((request != null) && (request.Form != null)) { string? login = request.Form["login"]; string? password = request.Form["password"]; if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password)) { context.Result = new BadRequestResult(); } if ((login != _login)||(password != _password)) context.Result = new UnauthorizedResult(); } else context.Result = new BadRequestResult(); } } }
В параметрах класса SimpleAuthorizeFilter
мы передаем логин и пароль пользователя. В методе OnResourceExecuting
мы проверяем какие логин и пароль ввел пользователь в форме и, если логин/пароль не заданы или не соответствуют переданным значениям в параметрах, то запрещаем пользователю доступ к ресурсу.
Теперь добавим в папку Models модель пользователя:
namespace AspResourceFilters.Models { public class User { public string Login { get; set; } public string Password { get; set; } } }
и, для примера, в папку «Views/Shared» представление UserPanel.cshtml со следующим содержанием:
<h2>Личный кабинет пользователя</h2>
Теперь добавим форму ввода логина/пароля в представление Views/Home/Index.cshtml:
@model User @{ ViewData["Title"] = "Home Page"; } @using (Html.BeginForm(FormMethod.Post)) { @Html.EditorForModel() <br/> <input type='submit' value='Отправить' /> } <div class="text-center"> <h1 class="display-4">Welcome</h1> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> </div>
и, наконец, применим фильтр к следующему методу контроллера HomeController
:
using AspResourceFilters.Models; using Microsoft.AspNetCore.Mvc; using AspResourceFilters.Filters; namespace AspResourceFilters.Controllers { public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult Index() { return View(); } [HttpPost] [SimpleAuthorizeFilter("admin","root")]//применяем фильтр public IActionResult Index(User user) { return View("UserPanel"); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } } }
Обратите внимание, что внутри метода Index()
мы уже ничего не проверяем — все проверки мы вынесли в код фильтра. Теперь можно запустить приложение и посмотреть на результат работы фильтра ресурсов:
ввели неверный пароль:
Вводим верный логин/пароль:
Аналогичным образом мы можем, например, добавить заголовок или установить cookie клиенту, чтобы, в дальнейшем использовать эти значения в работе фильтра.
Итого
Фильтры ресурсов в ASP.NET Core MVC выполняются сразу после фильтров авторизации и могут использоваться, например, для установления/анализа заголовков запроса, работы с кэшем (в особенности, если речь заходит о разработке API). Пример, рассмотренный выше, демонстрирует работу простейшей системы авторизации пользователя с использованием фильтра ресурсов.