J'ai du mal à spécifier deux attributs d'autorisation distincts sur une méthode de classe: l'utilisateur doit être autorisé à accéder si l'un des deux attributs est vrai.
La classe d'athorisation ressemble à ceci:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class AuthAttribute : AuthorizeAttribute {
. . .
et l'action:
[Auth(Roles = AuthRole.SuperAdministrator)]
[Auth(Roles = AuthRole.Administrator, Module = ModuleID.SomeModule)]
public ActionResult Index() {
return View(GetIndexViewModel());
}
Existe-t-il un moyen de résoudre ce problème ou dois-je repenser mon approche?
Il doit être exécuté dans MVC2.
Plusieurs instances AuthorizeAttribute
sont traitées par MVC comme si elles étaient jointes à AND
. Si vous voulez un comportement OR
, vous devrez implémenter votre propre logique pour les vérifications. Implémentez de préférence AuthAttribute
pour jouer plusieurs rôles et effectuer votre propre vérification avec la logique OR
.
Une autre solution consiste à utiliser AuthorizeAttribute
standard et à implémenter IPrincipal
personnalisé qui implémentera la méthode bool IsInRole(string role)
pour fournir un comportement 'OU'.
Un exemple est ici: https://stackoverflow.com/a/10754108/449906
Il existe une meilleure façon de le faire dans les versions ultérieures d'asp.net, vous pouvez faire les deux OR et AND sur les rôles. Cela se fait par convention, répertorier plusieurs rôles dans une seule autorisation effectuera une OR où l'ajout de plusieurs attributs d'autorisation effectuera AND.
OU exemple
[Authorize(Roles = "PowerUser,ControlPanelUser")]
ET Exemple
[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
Vous pouvez trouver plus d'informations à ce sujet sur le lien suivant https://docs.Microsoft.com/en-us/aspnet/core/security/authorization/roles
Je ne sais pas trop ce que les autres pensent de cela, mais je voulais aussi un comportement OR
. Dans mes AuthorizationHandler
s, je viens d'appeler Succeed
si l'un d'entre eux a réussi. Notez que cela n'a PAS fonctionné avec l'attribut Authorize
intégré qui n'a pas de paramètres.
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;
}
}
Fournissez votre propre LoggedInAuthReq. Au démarrage, injectez-les dans les services avec
services.AddAuthorization(o => {
o.AddPolicy("AadLoggedIn", policy => policy.AddRequirements(new LoggedInAuthReq()));
... more here
});
services.AddSingleton<IAuthorizationHandler, LoggedInHandler>();
... more here
Et dans votre méthode de contrôleur
[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,
};
}
Cela pourrait probablement aussi être accompli avec un seul attribut et un tas d'instructions if
. Il works for me
dans ce scénario. asp.net core 2.2 au moment de la rédaction de cet article.