Claims
Принципы авторизации и аутентификации в ASP.NET Core MVC не изменились по сравнению с предыдущей версией фреймворка, отличаясь лишь в деталях. Одним из относительно новых понятий является claim-based авторизация, с нее мы и начнем наше путешествие. Что же такое claim?
Это пара строк “ключ-значение”, в качестве ключа может выступать “FirstName”, “EmailAddress” и т.п. Таким образом, claim можно трактовать как свойство пользователя, как строку с данными, или даже как некоторое утверждение вида “у пользователя есть что-то”.
Знакомая многим разработчикам одномерная role-based модель органично содержится в многомерной claim-based модели: роль (утверждение вида “у пользователя есть роль X”) представляет собой один из claim и содержится в списке преопределенных System.Security.Claims.ClaimTypes. Не возбраняется создавать и свои claim.
Следующее важное понятие — identity. Это единое утверждение, содержащее набор claim. Так, identity можно трактовать как цельный документ (паспорт, водительские права и др.), в этом случае claim — строка в паспорте (дата рождения, фамилия…). В Core MVC используется класс System.Security.Claims.ClaimsIdentity.
Permission-based авторизация. свой фильтр авторизации
Декларативное перечисление всех запрашиваемых операций (в первую очередь из числа CRUD) при авторизации пользователя, такое как:
Resource-based авторизация
Как уже говорилось ранее, policy-based авторизация выполняется Core MVC в filter pipeline, т.е. ДО вызова защищаемого action. Успех авторизации при этом зависит только от пользователя — либо он обладает нужными claim, либо нет. А что, если необходимо учесть также защищаемый ресурс и его свойства, получить какие данные из внешних источников?
Пример из жизни: защищаем action вида GET /Orders/{id}, считывающий по id строку с заказом из БД. Пусть наличие у пользователя прав на конкретный заказ мы сможем определить только после получения этого заказа из БД. Это автоматически делает непригодными рассмотренные ранее аспектно-ориентированные сценарии на основе фильтров MVC, выполняемых перед тем, как пользовательский код получает управление. К счастью, в Core MVC есть способы провести авторизацию вручную.
Для этого, в контроллере нам потребуется реализацияIAuthorizationService. Получим ее, как обычно, через внедрение зависимости в конструктор:
public class ResourceController : Controller
{
IAuthorizationService _authorizationService;
public ResourceController(IAuthorizationService authorizationService)
{
_authorizationService = authorizationService;
}
}
Затем создадим новую политику и handler:
Авторизация
В нашем случае авторизация будет основана на использовании кукисов. Для этого изучим следующие положения:
Приступим.Создадим интерфейс IAuthentication и его реализацию CustomAuthentication (/Global/Auth/IAuthentication.cs):
Кукисы
Кукисы – это часть информации, отсылаемая сервером браузеру, которую браузер возвращает обратно серверу вместе с каждым (почти каждым) запросом.
Сервер в заголовок ответа пишет:
Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
Например:
Настройки политик доступа
Создание политик доступа через рассмотренный выше fluent-интерфейс не дает той гибкости, которая требуется в реальных приложениях. Конечно, можно явно указать допустимые значения claim через вызов RequireClaim(“x”, params values), можно скомбинировать через логическое И несколько условий, вызвав RequireClaim(“x”).
RequireClaim(“y”). Наконец, можно навесить на controller и action разные политики, что, впрочем, приведет к той же комбинации условий через логическое И. Очевидно, что необходим более гибкий механизм создания политик, и он у нас есть: requirements и handlers.
services.AddAuthorization(options =>
{
options.AddPolicy("age-policy",
policy => policy.Requirements.Add(new AgeRequirement(42), new FooRequirement()));
});
Подготовительные работы
Здесь и далее на протяжении статьи, мы будем настраивать доступ для различных страниц веб-сайта. Для запуска представленного кода, достаточно создать в Visual Studio 2022 новое приложение типа “ASP.NET Core Web Application”, задать шаблон Web Application и тип аутентификации “No Authentication”.