Передача параметров в Требование/Политика в ASP.NET MVC 6
Я пытался создать собственный атрибут авторизации в ASP.NET vNext, пока не нашел этот отличный ответ от @blowdart в этом сообщении:
qaru.site/info/42950/...
указав, что теперь требования авторизации - это путь. Ответ очень проясняет, но не указывает, как передать параметр этим требованиям/политикам.
То, что я пытаюсь сделать, это портирование атрибута авторизации MVC 5, который имеет эту подпись:
[Autorizacion(Requires = enumPermission.DeleteCustomer)]
так как я использую очень настроенный набор разрешений, зеркально отраженных в backend/frontend как enums/strings.
Поскольку эти функции все еще не документированы, я чувствую себя немного потерянным... Может ли кто-нибудь дать указания?
Заранее спасибо
Ответы
Ответ 1
Действительно, пост @blowdarts очень проницателен, и из моего понимания ключевое значение для понимания заключается в следующем:
Авторизация действует на Identities. Тождества создаются аутентификации.
Итак, похоже, что идентификаторы создаются процессом аутентификации.
Затем (если хотите) вы можете запустить процесс авторизации. Это означает создание пользовательского authorization requirements
, которому это требование будет смотреть на эти тождества и действовать на них.
На простом английском языке это то, что, я считаю, происходит:
-
Как уже упоминалось в postdarts post, у нас должны быть какие-то
промежуточное программное обеспечение аутентификации, которое
аутентификация. После успешной аутентификации вы берете
информацию, которую вы хотите получить от этого пользователя, прошедшего проверку подлинности, и создать
аутентифицирован ClaimsPrincipal
.
Например, мы могли бы сохранить в этом ClaimsPrincipal
, множества
разрешение пользователя.
-
Затем, когда вы создаете свой authorization requirement
, вы смотрите на
ClaimsPrincipal
, извлеките набор разрешений из
ClaimsPrincipal
и предпринять соответствующие действия на основе
бизнес-правила, которые вы хотите.
Предполагая, что вы не можете хранить наборы разрешений в
ClaimsPrincipal
по какой-то причине можно было легко сохранить UserId
и из этого требования прочитайте, что UserId из
ClaimsPrincipal
, вызвать базу данных и получить наборы разрешений
и затем действовать на них.
Вывод:
Короче говоря, я не думаю, что вы передаете материал требованиям (требованиям), я думаю, что вы получите их из .
В вашем примере вы можете создать требование, которое читает ClaimsPrincipal
и сравнивает любое значение с вашим Enum
и воздействует на это.
Сообщите нам, что вам удалось сделать, и если оно работает.
И если мое понимание этого неверно, то, во всяком случае, не стесняйтесь исправлять меня, потому что все это новый материал: -)
Ответ 2
Я случайно нашел подходящее решение, которое может удовлетворить мои требования, надеюсь, оно вам тоже поможет.
В моем случае мне нужно передать IHttpContextAccessor
и EFCore AppDbContext
в мой класс Requirement.
в моем Startup.cs
я пишу что-то вроде этого:
services.AddAuthorization(options =>
{
options.AddPolicy("ThePolicy", policy => policy.Requirements.Add( new ThePolicyRequirement() ));
});
services.AddScoped<IAuthorizationHandler, ThePolicyAuthorizationHandler>();
класс ThePolicyAuthorizationHandler
:
public class ThePolicyAuthorizationHandler : AuthorizationHandler<ThePolicyRequirement>
{
readonly AppDbContext _appContext;
readonly IHttpContextAccessor _contextAccessor;
public ThePolicyAuthorizationHandler(AppDbContext c, IHttpContextAccessor ca)
{
_appContext = c;
_contextAccessor = ca;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ThePolicyRequirement requirement)
{
var result = await requirement.isPass(_appContext, _contextAccessor, context);
if (result)
context.Succeed(requirement);
else
context.Fail(requirement);
}
}
и класс ThePolicyRequirement
:
public class ThePolicyRequirement : IAuthorizationRequirement
{
AppDbContext _context;
IHttpContextAccessor _contextAccessor;
AuthorizationHandlerContext _authHandlerContext;
public async Task<bool> isPass(AppDbContext context, IHttpContextAccessor contextAccessor, AuthorizationHandlerContext authorizationHandlerContext)
{
_context = context;
_contextAccessor = contextAccessor;
_authHandlerContext = authorizationHandlerContext;
//logic here
return result;
}
}
Ключевая идея заключается в использовании ThePolicyAuthorizationHandler
для получения как можно большего количества всех необходимых объектов и передачи его в ThePolicyRequirement
для выполнения логики механизма авторизации.