Множественные атрибуты авторизации по методу
У меня возникли проблемы с указанием двух отдельных атрибутов авторизации для метода класса: пользователю разрешен доступ, если любой из двух атрибутов имеет значение true.
Класс Athorization выглядит следующим образом:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class AuthAttribute : AuthorizeAttribute {
. . .
и действие:
[Auth(Roles = AuthRole.SuperAdministrator)]
[Auth(Roles = AuthRole.Administrator, Module = ModuleID.SomeModule)]
public ActionResult Index() {
return View(GetIndexViewModel());
}
Есть ли способ решить эту проблему или мне нужно переосмыслить мой подход?
Это должно быть запущено в MVC2.
Ответы
Ответ 1
Несколько экземпляров AuthorizeAttribute
обрабатываются MVC, как если бы они были соединены с AND
. Если вы хотите поведение OR
, вам нужно будет реализовать свою собственную логику проверок. Предпочтительно реализовать AuthAttribute
для выполнения нескольких ролей и выполнить собственную проверку с помощью логики OR
.
Другим решением является использование стандартного AuthorizeAttribute
и реализация пользовательского IPrincipal
, который будет реализовывать метод bool IsInRole(string role)
для обеспечения поведения "OR".
Пример:
fooobar.com/questions/351716/...
Ответ 2
Есть лучший способ сделать это в более поздних версиях asp.net, вы можете делать как OR, так и AND в ролях. Это делается с помощью соглашения, в котором перечислены несколько ролей в одном авторизованном режиме, будет выполняться OR, где добавление нескольких атрибутов авторизации будет выполнять AND.
ИЛИ пример
[Authorize(Roles = "PowerUser,ControlPanelUser")]
И пример
[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
Дополнительную информацию об этом можно найти по следующей ссылке
https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles
Ответ 3
Я не уверен, что другие думают об этом, но я тоже хотел поведение OR
. В моем AuthorizationHandler
я только что позвонил Succeed
, если кто-нибудь из них прошел. Обратите внимание, что это НЕ работает со встроенным атрибутом Authorize
, который не имеет параметров.
public class LoggedInHandler : AuthorizationHandler<LoggedInAuthReq>
{
private readonly IHttpContextAccessor httpContextAccessor;
public LoggedInHandler(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, LoggedInAuthReq requirement)
{
var httpContext = httpContextAccessor.HttpContext;
if (httpContext != null && requirement.IsLoggedIn())
{
context.Succeed(requirement);
foreach (var req in context.Requirements)
{
context.Succeed(req);
}
}
return Task.CompletedTask;
}
}
Предоставьте свой собственный LoggedInAuthReq. При запуске введите их в сервисы с помощью
services.AddAuthorization(o => {
o.AddPolicy("AadLoggedIn", policy => policy.AddRequirements(new LoggedInAuthReq()));
... more here
});
services.AddSingleton<IAuthorizationHandler, LoggedInHandler>();
... more here
И в вашем методе контроллера
[Authorize("FacebookLoggedIn")]
[Authorize("MsaLoggedIn")]
[Authorize("AadLoggedIn")]
[HttpGet("anyuser")]
public JsonResult AnyUser()
{
return new JsonResult(new { I = "did it with Any User!" })
{
StatusCode = (int)HttpStatusCode.OK,
};
}
Это, вероятно, также может быть выполнено с помощью одного атрибута и набора операторов if
. Это works for me
в этом сценарии. asp.net core 2.2 на момент написания статьи.