Benutzerdefinierte Autorisierung in Asp.net WebApi - was für ein Durcheinander?

113

Ich lese aus verschiedenen Quellen (Bücher und SO-Antworten) über die Autorisierung in WebApi.

Angenommen, ich möchte ein benutzerdefiniertes Attribut hinzufügen, das den Zugriff nur für bestimmte Benutzer ermöglicht:

Fall 1

Ich habe diesen Ansatz des Überschreibens gesehen OnAuthorization , der die Reaktion festlegt, wenn etwas nicht stimmt

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 public override void OnAuthorization(HttpActionContext actionContext)
  {
   if ( /*check if user OK or not*/)
   {
     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
   }
  }
}

Fall 2

Aber ich habe auch dieses ähnliche Beispiel gesehen, das ebenfalls OnAuthorizationaußer Kraft gesetzt wurde, aber mit dem Aufruf an base:

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
  base.OnAuthorization(actionContext);

    // If not authorized at all, don't bother

    if (actionContext.Response == null)  
     {
      //...
     }
}

Dann prüfen Sie, ob das HttpActionContext.Responseeingestellt ist oder nicht. Wenn es nicht festgelegt ist, bedeutet dies, dass die Anforderung autorisiert ist und der Benutzer in Ordnung ist

Fall 3

Aber ich habe auch diesen Ansatz des Überschreibens gesehen IsAuthorized :

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
 protected override bool IsAuthorized(HttpActionContext context)
  {
   if ( /*check if user OK or not*/)
   {
    return true;// or false
   }
  }
}

Fall 4

Und dann habe ich ein ähnliches Beispiel gesehen, aber mit dem Aufruf von base.IsAuthorized (Kontext):

protected override bool IsAuthorized(HttpActionContext context)
{
 if (something1 && something2 && base.IsAuthorized(context)) //??
 return true;
 return false;
}

Eine Sache noch

Und schließlich sagte Dominick hier :

Sie sollten OnAuthorization nicht überschreiben, da Ihnen die Behandlung mit [AllowAnonymous] fehlen würde.

Fragen

  • 1) Welche Methoden soll ich anwenden: IsAuthorizedoder OnAuthorization? (oder wann man welche benutzt)

  • 2) Wann soll ich base.IsAuthorized orbase.OnAuthorization anrufen?

  • 3) Haben sie es so gebaut? dass, wenn die Antwort null ist, dann ist alles in Ordnung? (Fall 2)

NB

Bitte beachten Sie, dass ich nur AuthorizeAttributedas verwende (und verwenden möchte), von dem bereits geerbt wurde AuthorizationFilterAttribute

Warum ?

Weil ich mich in der ersten Phase befinde in: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

Geben Sie hier die Bildbeschreibung ein

Wie auch immer, ich frage über die Erweiterung des Authorize-Attributs.

Royi Namir
quelle
Was benötigen Sie, um das Authorize-Attribut zu überschreiben? Was ist der Anwendungsfall, den Sie erreichen möchten? Wenn Sie bestimmten Benutzern den Zugriff erlauben müssen, warum nicht das Attribut [Authorize (Users = "Admin")] wie dieses verwenden?
Taiseer Joudeh
1
@TaiseerJoudeh Versuchen Sie beispielsweise, Benutzer zwischen 10:00 und 12:00 Uhr zu autorisieren (konfigurierbar). Sie können das nicht mit einfachen Rollen und autorisierten attr tun. Sie müssen Ihre eigene Logik machen
Royi Namir

Antworten:

93

Welche Methoden sollte ich verwenden: IsAuthorized oder OnAuthorization? (oder wann man welche benutzt)

Sie verlängern, AuthorizationFilterAttributewenn Ihre Berechtigungslogik nicht von der festgelegten Identität und den Rollen abhängt. Für die benutzerbezogene Autorisierung werden Sie erweitern und verwenden AuthorizeAttribute. Für den ersteren Fall werden Sie überschreiben OnAuthorization. Im letzteren Fall werden Sie überschreiben IsAuthorized. Wie Sie dem Quellcode dieser Attribute OnAuthorizationentnehmen können , ist es als virtuell markiert, damit Sie es überschreiben können, wenn Sie von ableiten AuthorizationFilterAttribute. Andererseits ist die IsAuthorizedMethode in als virtuell markiert AuthorizeAttribute. Ich glaube, dies ist ein guter Hinweis auf die beabsichtigte Verwendung.

Wann soll ich base.IsAuthorized oder base.OnAuthorization aufrufen?

Die Antwort auf diese Frage liegt darin, wie OO im Allgemeinen funktioniert. Wenn Sie eine Methode überschreiben, können Sie entweder eine neue Implementierung vollständig bereitstellen oder auf die vom übergeordneten Element bereitgestellte Implementierung zurückgreifen und das Verhalten verbessern. Nehmen Sie zum Beispiel den Fall von IsAuthorized(HttpActionContext). Das Verhalten der Basisklasse besteht darin, den Benutzer / die Rolle mit den Angaben im Filter und der festgelegten Identität zu vergleichen. Angenommen, Sie möchten all das tun, aber zusätzlich möchten Sie etwas anderes überprüfen, das möglicherweise auf einem Anforderungsheader oder etwas anderem basiert. In diesem Fall können Sie eine solche Überschreibung bereitstellen.

protected override bool IsAuthorized(HttpActionContext actionContext)
{
    bool isAuthroized = base.IsAuthorized(actionContext);
    // Here you look at the header and do your additional stuff based on actionContext
    // and store the result in isRequestHeaderOk
    // Then, you can combine the results
    // return isAuthorized && isRequestHeaderOk;
}

Es tut mir leid, aber ich verstehe dein Q3 nicht. Übrigens gibt es den Autorisierungsfilter schon lange und die Leute verwenden ihn für alle möglichen Dinge und manchmal auch falsch.

Eine Sache noch. Und schließlich war da dieser Typ, der sagte: Sie sollten OnAuthorization nicht überschreiben - weil Ihnen die Handhabung von [AllowAnonymous] fehlen würde.

Der Typ, der das gesagt hat, ist der Gott der Zugangskontrolle - Dominick. Offensichtlich wird es richtig sein. Wenn Sie sich die Implementierung von OnAuthorization(unten kopiert) ansehen ,

public override void OnAuthorization(HttpActionContext actionContext)
{
    if (actionContext == null)
    {
        throw Error.ArgumentNull("actionContext");
    }

    if (SkipAuthorization(actionContext))
    {
        return;
    }

    if (!IsAuthorized(actionContext))
    {
        HandleUnauthorizedRequest(actionContext);
    }
}

Der Aufruf von SkipAuthorizationist der Teil, der sicherstellt AllowAnonymous, dass Filter angewendet werden, dh die Autorisierung wird übersprungen. Wenn Sie diese Methode überschreiben, verlieren Sie dieses Verhalten. Wenn Sie sich dazu entschließen, Ihre Berechtigung auf Benutzer / Rollen zu stützen, hätten Sie sich zu diesem Zeitpunkt entschieden, davon abzuleiten AuthorizeAttribute. Die einzig richtige Option, die zu diesem Zeitpunkt für Sie übrig bleibt, ist das Überschreiben IsAuthorizedund nicht das bereits überschriebene OnAuthorization, obwohl dies technisch möglich ist.

PS. In der ASP.NET-Web-API gibt es einen anderen Filter, den Authentifizierungsfilter. Die Idee ist, dass Sie diesen Filter für die Authentifizierung und den Autorisierungsfilter für die Autorisierung verwenden, wie der Name schon sagt. Es gibt jedoch viele Beispiele, bei denen diese Grenze verfälscht ist. Viele Beispiele für Authentifizierungsfilter führen eine Art Authentifizierung durch. Wenn Sie Zeit haben und etwas mehr verstehen möchten, lesen Sie diesen MSDN- Artikel . Haftungsausschluss: Es wurde von mir geschrieben.

Badri
quelle
Nochmals vielen Dank, aber wenn ich zwischen den Zeilen lese, wird IsAuthenticated von OnAuthirization aufgerufen. Warum also nicht OnAuthorization und call base.OnAuthorization überschreiben und dann die Antwort überprüfen?
Royi Namir
Sie können sicher, wenn es das ist, was Sie wollen.
Badri
In meiner dritten Frage meinte ich: Nachdem Sie die Basisfunktion - base.OnAuthorization zum Beispiel - ausgeführt haben, können Sie nur überprüfen, ob sie erfolgreich war, indem Sie die Response-Eigenschaft überprüfen. Ps Die Beispiele stammen aus Ihrem Buch :-)
Royi Namir
Ja, normalerweise suchen Sie nach dem 401-Statuscode, aber meines Wissens nicht nach null. Übrigens erinnere ich mich nicht daran, OnAuthorizationin meinem Buch über das Überschreiben geschrieben zu haben. Ich bin sicher, ich hätte nicht darüber geschrieben, die Antwort auf Null zu überprüfen, denn dies ist das erste Mal, dass ich davon höre :)
Badri
Ja, ich wurde mit dem anderen Buch verwechselt. Ich lese 3 Bücher gleichzeitig: sicher (deins), praktisch (deins) und webapi pro (Tugberk's, Zeitler, Ali). Wie Sie sehen können - sie haben es dort getan : i.stack.imgur.com/LNGi4.jpg - sie haben nur überprüft, ob null, also sollte ich null oder Fehlercodes überprüfen?
Royi Namir
17

Ok, mein Vorschlag ist, Folgendes zu tun, vorausgesetzt, Sie verwenden OAuth-Inhaber-Token, um Ihre Web-API zu schützen, und Sie legen die erlaubte Zeit als Anspruch für den Benutzer fest, als Sie das Token ausgestellt haben. Weitere Informationen zur tokenbasierten Authentifizierung finden Sie hier

  1. Erstellen Sie CustomAuthorizeAttribute, das von AuthorizationFilterAttribute abgeleitet ist
  2. Überschreiben Sie die Methode OnAuthorizationAsyncund verwenden Sie den folgenden Beispielcode:

     public class CustomAuthorizeAttribute : AuthorizationFilterAttribute
    {
    
        public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
    
            var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;
    
            if (!principal.Identity.IsAuthenticated)
            {
                return Task.FromResult<object>(null);
            }
    
            var userName = principal.FindFirst(ClaimTypes.Name).Value;
            var userAllowedTime = principal.FindFirst("userAllowedTime").Value;
    
            if (currentTime != userAllowedTime)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla");
                return Task.FromResult<object>(null);
            }
    
            //User is Authorized, complete execution
            return Task.FromResult<object>(null);
    
        }
    }
    
  3. Jetzt verwenden Sie in Ihren Controllern das CustomAuthorize-Attribut, um Ihre Controller mithilfe dieser Autorisierungslogik zu schützen.
Taiseer Joudeh
quelle
1
Vielen Dank. Aber ich benutze gerade, AuthorizeAttributewas erbt AuthorizationFilterAttributeund -auch zum Lernen. Ich habe speziell gefragt, welche Methode ich verwenden soll und ob die Antwort Inhalt hat oder nicht ...
Royi Namir
3

ASP.NET v5 Einführung eines völlig neuen Autorisierungssystems. Für diejenigen, die .NET 5 verwenden möchten, würde ich empfehlen, in Microsoft.AspNet.Authorization zu wechseln.

Ziemlich viel wickelt es die mess up verursacht durch beide zu halten System.Web.Http.Authorizeund System.Web.Mvc.Authorizeauch andere , ältere Authentifizierungsimplementierungen.

Es bietet eine sehr gute Abstraktion von Aktionstypen (Erstellen, Lesen, Aktualisieren, Löschen), Ressourcen, Rollen, Ansprüchen, Ansichten und benutzerdefinierten Anforderungen und ermöglicht das Erstellen benutzerdefinierter Handler, wobei eine der oben genannten kombiniert wird. Darüber hinaus können diese Handler auch in Kombination verwendet werden.

In ASP.NET v5 bietet die Autorisierung jetzt eine einfache deklarative Rolle und ein umfassenderes richtlinienbasiertes Modell, bei dem die Autorisierung in Anforderungen ausgedrückt wird und Handler die Ansprüche eines Benutzers anhand von Anforderungen bewerten. Imperative Überprüfungen können auf einfachen Richtlinien oder Richtlinien basieren, die sowohl die Benutzeridentität als auch die Eigenschaften der Ressource bewerten, auf die der Benutzer zugreifen möchte.

Anestis Kivranoglou
quelle
14
Gut zu wissen, beantwortet aber die Frage überhaupt nicht.
Zero3