it-swarm.com.de

Attribut mit mehreren Rollen autorisieren

Ich möchte einem Controller die Autorisierung für mehrere Rollen gleichzeitig hinzufügen.

Normalerweise würde das so aussehen:

[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}

Ich habe aber meine Rollen in consts gespeichert, da sie sich irgendwann ändern oder erweitern könnten.

public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";

Ich kann dies nicht tun, da der String zur Kompilierzeit bekannt sein muss:

[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}

Gibt es eine Möglichkeit, das Problem zu umgehen?

Ich könnte einen const schreiben, der einfach "RoleA, RoleB, RoleC" enthält - aber mag magische Saiten nicht und das ist eine magische Saite. Das Ändern des Namens einer Rolle und das Vergessen, die kombinierte Zeichenfolge zu ändern, wäre ein Desaster.

Ich verwende MVC5. ASP.NET-Identität und die Rolle sind zur Kompilierzeit bekannt.

76
Christian Sauer

Versuchen Sie, ein benutzerdefiniertes Berechtigungsattribut wie this zu erstellen.

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = string.Join(",", roles);
    }
}

Wenn Sie davon ausgehen, dass Ihre Rollen für mehrere Controller gleich sind, erstellen Sie eine Hilfsklasse:

public static class Role
{
    public const string Administrator = "Administrator";
    public const string Assistant = "Assistant";
}

Dann benutze es wie folgt:

public class MyController : Controller
{
    [AuthorizeRoles(Role.Administrator, Role.Assistant)]
    public ActionResult AdminOrAssistant()
    {                       
        return View();
    }
}
146
MacGyver

Stellen Sie sicher, dass Sie Ihre benutzerdefinierte Attributklasse von System.Web.Mvc.AuthorizeAttribute und NICHT System.Web.Http.AuthorizeAttribute ableiten.

Ich bin auf das gleiche Problem gestoßen. Nachdem ich es geändert hatte, funktionierte alles.

Sie können der benutzerdefinierten Attributklasse auch Folgendes hinzufügen:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
8
Jerry Finegan

Der beste und einfachste Weg, das ich gefunden habe, um dieses Problem zu lösen, besteht darin, Rollen im Authorize-Attribut zu verketten.

[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]

mit CustomRole eine Klasse mit konstanten Zeichenfolgen wie folgt: 

public static class CustomRoles
{
    public const string Admin = "Admin";
    // and so on..
}
6
ChristopheHvd

Was ich getan habe, ist die Antwort in @Tieson

Ich tweak ein wenig in seiner Antwort. Anstelle von string.Join, warum nicht in Liste konvertieren?

Hier ist meine Antwort:

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    private new List<string> Roles;
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = roles.toList()
    }
}

Überprüfen Sie dann, ob die Rolle gültig ist und OnAuthorization überschreibt

public override void OnAuthorization(HttpActionContext actionContext)
{
            if (Roles == null)
                HandleUnauthorizedRequest(actionContext);
            else
            {
                ClaimsIdentity claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity;
                string _role = claimsIdentity.FindFirst(ClaimTypes.Role).Value;
                bool isAuthorize = Roles.Any(role => role == _role);

                if(!isAuthorize)
                    HandleUnauthorizedRequest(actionContext);
            }
        }

Und dort haben Sie es. Jetzt wird geprüft, ob die Rolle für den Zugriff auf die Ressource berechtigt ist

Ich habe das Gefühl, dass ein benutzerdefiniertes Berechtigungsattribut für dieses Problem zu viel ist, es sei denn, Sie haben eine große Anzahl von Rollen.

Da die Zeichenfolge zur Kompilierzeit bekannt sein muss, können Sie eine statische Rollenklasse erstellen, die öffentliche Zeichenfolgen der von Ihnen definierten Rollen enthält, und dann durch Kommas getrennte Zeichenfolgen mit bestimmten Rollen hinzufügen, die Sie autorisieren möchten: 

public static class Roles
{
    public const string ADMIN = "Admin";
    public const string VIEWER = "Viewer";

    public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}

Und dann können Sie das Berechtigungsattribut wie in der Controller-Klasse oder der Controller-Methode (oder beiden) verwenden:

[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
    [Authorize(Roles = Roles.ADMIN_OR_VIEWER)
    public ActionResult Create()
    {
        ..code here...
    }
}
0
Robert Tuttle