MVC5 Claims-Version des Authorize-Attributs

77

Ich probiere einige der neuen Dinge in VS2013 RC mit MVC5 und der neuen OWIN-Authentifizierungs-Middleware aus.

Ich bin es also gewohnt, das [Authorize]Attribut zu verwenden, um Aktionen nach Rollen einzuschränken, aber ich versuche, eine auf Ansprüchen / Aktivitäten basierende Berechtigung zu verwenden, und ich kann kein gleichwertiges Attribut dafür finden.

Gibt es eine offensichtliche, die ich vermisse, oder muss ich meine eigene rollen? Ich habe irgendwie erwartet, dass es einen Out of the Box gibt.

Was ich speziell suche, ist etwas in der Art, wie [Authorize("ClaimType","ClaimValue")]ich es nehme.

Danke im Voraus.

EightyOne Unite
quelle
1
Nur als Vorschlag, setzen Sie bitte den UPDATE-Abschnitt als neue Antwort, so dass für alle klar ist, dass es ein anderer Ansatz ist (und nicht Teil Ihrer Frage)
g3rv4
Ich würde das tun, aber dann würde ich meine eigene Antwort akzeptieren wollen, und das ist einfach nicht das, was ein Gentleman tut :-)
EightyOne Unite
1
Ich habe genau das auf Meta gefragt und hier ist, was sie auf meta.stackexchange.com/questions/216719/… geantwortet haben, also scheint es einen Konsens zu geben;)
g3rv4
@ Stimul8d Ich muss Gervasio zustimmen - Fragen sind für Fragen, Antworten sind für Antworten. Sie müssten es nicht als akzeptiert markieren, wenn Sie es nicht möchten. aber es würde es für andere Menschen klarer machen.
Dav_i
2
Ich finde es brutal, dass diese Technologie im Vergleich zur Implementierung für Rollen nicht mit der Installation von Attributen geliefert wurde.
Pittsburgh DBA

Antworten:

73

Am Ende habe ich nur ein einfaches Attribut geschrieben, um damit umzugehen. Ich konnte nichts im Framework sofort finden, ohne ein paar zusätzliche Konfigurationen. Nachfolgend aufgeführten.

public class ClaimsAuthorizeAttribute : AuthorizeAttribute
{
    private string claimType;
    private string claimValue;
    public ClaimsAuthorizeAttribute(string type, string value)
    {
        this.claimType = type;
        this.claimValue = value;
    }
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var user = filterContext.HttpContext.User as ClaimsPrincipal;
        if (user != null && user.HasClaim(claimType, claimValue))
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

Natürlich könnten Sie die Parameter type und value entfernen, wenn Sie das Controller-Action-Verb-Triplett gerne für Ansprüche verwenden würden.

EightyOne Unite
quelle
6
Aus Gründen der Vorwärtskompatibilität ist es am besten, diese zu verwenden filterContext.HttpContext.user.
Erik Philips
1
Am Ende habe ich etwas fast Identisches gemacht, aber es erzwingt eine rollenartige Mentalität in Bezug auf die Anwendung der Attribute. Die Trennung von Bedenken, für die sich @leastprivilege einsetzt, sieht viel stärker aus.
Pittsburgh DBA
2
@ Stimul8d Danke für die Antwort, das hat in meiner MVC 5 App perfekt geklappt! Für mich ist es sinnvoller, Ihr eigenes ClaimsAuthorizationAttribute zu implementieren, als mit dem ClaimsAuthorizationManager (zu viel Konfiguration erforderlich)
landsteven
1
Gute Antwort, vor allem, weil selbst ich sie verstehen und integrieren konnte.
Vasily Hall
Eine gute Antwort - Ich habe ein HTTP 403 zurückgegeben, um zu verhindern, dass Sie zur Anmeldeseite zurückkehren. Sie können Rollen ähnlich wie Ansprüche verwenden. Verwenden Sie anstelle einer einzelnen Geschäftsrolle wie ADMIN viele Rollen wie CanSaveData. Sie möchten eine benutzerdefinierte Tabelle, die die Pseudorolle ADMIN allen Rollen zuordnet, denen sie angehört. Ansprüche ist der Weg, den Sie gehen, wie es eingebaut ist
pixelda
30
  1. Sie würden nicht speziell nach Ansprüchen suchen, sondern nach Aktions- / Ressourcenpaaren. Berücksichtigen Sie die tatsächlichen Ansprüche / Datenprüfungen in einem Berechtigungsmanager. Trennung von Bedenken.
  2. MVC und ClaimsPrincipalPermission passen nicht gut zusammen. Es löst eine SecurityException aus und ist nicht für Unit-Tests geeignet.

Meine Version ist hier: http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/

geringstes Privileg
quelle
2
Ihre Version scheint nicht im neuesten MVC 5-Build zu sein? Wenn ja, welches Nuget-Paket enthält es?
Brian Mains
2
nuget.org/packages/Thinktecture.IdentityModel.SystemWeb - und es wird in ResourceActionAuthorizeAttribute umbenannt
geringstes Privileg
4
@leastprivilege Ich denke, es wäre sinnvoll, Ihren Blog-Beitrag mit Informationen über das umbenannte Attribut und die verfügbaren Nuget-Pakete für MVC und Web API 2.x zu aktualisieren . Ich weiß nicht, wie ich über die Umbenennung hätte Bescheid wissen sollen, wenn es diesen Kommentarbereich nicht gegeben hätte;)
Lasse Christiansen
4
Ich weiß nicht, ob diese Antwort noch aktuell ist, aber ich habe noch keine Ahnung, was eine Ressource ist oder was sie mit Controller-Aktionen und den Behauptungen zu tun hat, die ich habe. Könnten Sie als jemand, der kein Owin-Experte ist, die Antwort bitte ein wenig erweitern?
Craig Brett
1
Die Verwendung eines Attributs ist nach wie vor ein Problem, da sich die Logik im Attributcode befindet und die Attributeigenschaft für den Entwickler nahe genug bleibt, damit er sie nicht vergisst.
Softlion
9

Ich habe festgestellt, dass Sie das Berechtigungsattribut weiterhin mit Rollen und Benutzern mit Ansprüchen verwenden können.
Damit dies funktioniert, muss Ihre ClaimsIdentity zwei bestimmte Anspruchstypen enthalten:

    ClaimTypes.Name

und

    ClaimTypes.Role

Fügen Sie dann in Ihrer von OAuthAuthorizationServerProvider abgeleiteten Klasse in den von Ihnen verwendeten GrantXX-Methoden beim Erstellen Ihrer ClaimsIdentity diese beiden Ansprüche hinzu.

Beispiel:

    var oAuthIdentity = new ClaimsIdentity(new[]
    {
        new Claim(ClaimTypes.Name, context.ClientId),
        new Claim(ClaimTypes.Role, "Admin"),
    }, OAuthDefaults.AuthenticationType);

Dann können Sie bei jeder Aktion [Authorize(Roles ="Admin")]den Zugriff einschränken.

Softlion
quelle
Das macht den Trick! Was mich auffiel, war, den Token nach den Änderungen nicht neu zu generieren - doh! Um klar zu sein, müssen Sie mit dem obigen Code [Authorize (Roles = "Admin")] den Zugriff auf eine Methode einschränken.
Kinetic
4

In ASP.NET Core 3 können Sie Sicherheitsrichtlinien wie folgt konfigurieren:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

Verwenden Sie dann AuthorizeAttribute, um vom Benutzer zu verlangen, dass er die Anforderungen einer bestimmten Richtlinie erfüllt (mit anderen Worten, erfüllen Sie den Anspruch, der diese Richtlinie unterstützt).

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

Quelle .

Eric J.
quelle
3
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation="Delete", Resource="Customer")]
public ActionResult Delete(int id)
{
    _customer.Delete(id);
    return RedirectToAction("CustomerList");
}

ClaimsPrincipalPermissionAttribute-Klasse

jd4u
quelle
2
Es scheint ungefähr richtig zu sein, aber es ist eine Menge Beinarbeit und zusätzliche Referenzen für etwas, das eingebrannt werden soll. Ich habe die Antwort akzeptiert, aber meine Bearbeitung überprüft.
EightyOne Unite
1
Löst dies nicht eine Ausnahme aus, anstatt eine entsprechende HTTP-Antwort zurückzugeben?
Ronnie Overby