Autorizzazione personalizzata in Asp.net WebApi: che casino?


113

Sto leggendo da diverse risorse (libri e risposte SO) sull'autorizzazione in WebApi.

Supponiamo di voler aggiungere un attributo personalizzato che consente l'accesso solo a determinati utenti:

Caso 1

Ho visto questo approccio di override OnAuthorization , che imposta la risposta se qualcosa non va

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

Caso n. 2

Ma ho anche visto questo esempio simile che ha anche la precedenza OnAuthorizationma con la chiamata a base:

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

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

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

Quindi, controlli se HttpActionContext.Responseè impostato o meno. Se non è impostato, significa che la richiesta è autorizzata e l'utente è ok

Caso n. 3

Ma ho anche visto questo approccio di override IsAuthorized :

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

Caso n. 4

E poi ho visto un esempio simile ma con la chiamata di base.IsAuthorized (context):

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

Un'altra cosa

E infine Dominick ha detto qui :

Non dovresti sovrascrivere OnAuthorization - perché mancherebbe la gestione di [AllowAnonymous].

Domande

  • 1) Quali metodi dovrei usare: IsAuthorizedo OnAuthorization? (o quando usare quale)

  • 2) quando devo chiamare base.IsAuthorized orbase.OnAuthorization`?

  • 3) È così che l'hanno costruito? che se la risposta è nulla allora va tutto bene? (caso # 2)

NB

Si prega di notare, sto usando (e voglio usare) solo quello AuthorizeAttributeche già eredita da AuthorizationFilterAttribute

Perché ?

Perché sono al primo stadio in: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

inserisci qui la descrizione dell'immagine

Comunque sto chiedendo tramite l'estensione dell'attributo Authorize.


Di cosa hai bisogno per sostituire l'attributo Authorize? Qual è il caso d'uso che vuoi ottenere? Se è necessario consentire l'accesso a determinati utenti, perché non utilizzare l'attributo [Authorize (Users = "Admin")] in questo modo?
Taiseer Joudeh

1
@TaiseerJoudeh Ad esempio, prova ad autenticare gli utenti tra le 10:00 e le 12:00 (configurabile). non puoi farlo con ruoli semplici e attr autorizzato. devi creare la tua logica
Royi Namir

Risposte:


93

Quali metodi dovrei usare: IsAuthorized o OnAuthorization? (o quando usare quale)

Si estenderà AuthorizationFilterAttributese la logica di autorizzazione non dipende dall'identità stabilita e dai ruoli. Per l'autorizzazione relativa all'utente, estenderai e utilizzerai AuthorizeAttribute. Nel primo caso, sostituirai OnAuthorization. In quest'ultimo caso, sostituirai IsAuthorized. Come puoi vedere dal codice sorgente di questi attributi, OnAuthorizationè contrassegnato come virtuale da sovrascrivere se derivi da AuthorizationFilterAttribute. D'altra parte, il IsAuthorizedmetodo è contrassegnato come virtuale in AuthorizeAttribute. Credo che questo sia un buon indicatore dell'uso previsto.

quando devo chiamare base.IsAuthorized o base.OnAuthorization?

La risposta a questa domanda sta nel modo in cui funziona generalmente l'OO. Se si sovrascrive un metodo, è possibile fornire completamente una nuova implementazione o eseguire il backup dell'implementazione fornita dal genitore e migliorare il comportamento. Ad esempio, prendi il caso di IsAuthorized(HttpActionContext). Il comportamento della classe base consiste nel verificare l'utente / ruolo rispetto a quanto specificato nel filtro rispetto all'identità stabilita. Diciamo che vuoi fare tutto questo, ma in aggiunta, vuoi controllare qualcos'altro, potrebbe essere basato su un'intestazione di richiesta o qualcosa del genere. In tal caso, puoi fornire una sostituzione come questa.

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;
}

Mi dispiace ma non capisco la tua Q3. A proposito, il filtro di autorizzazione è in circolazione da molto tempo e le persone lo usano per tutti i tipi di cose e talvolta anche in modo errato.

Un'altra cosa. E alla fine c'era questo tizio qui che ha detto: Non dovresti sovrascrivere OnAuthorization - perché ti mancherebbe la gestione di [AllowAnonymous].

Il ragazzo che ha detto che è il Dio del controllo degli accessi - Dominick. Ovviamente sarà corretto. Se guardi l'implementazione di OnAuthorization(copiato di seguito),

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

    if (SkipAuthorization(actionContext))
    {
        return;
    }

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

la chiamata a SkipAuthorizationè la parte che garantisce l'applicazione dei AllowAnonymousfiltri, ovvero l'autorizzazione viene ignorata. Se ignori questo metodo, perdi quel comportamento. In realtà, se decidi di basare la tua autorizzazione su utenti / ruoli, a quel punto avresti deciso di derivare da AuthorizeAttribute. L'unica opzione corretta rimasta per te a quel punto sarà quella di sovrascrivere IsAuthorizede non quella già sovrascritta OnAuthorization, sebbene sia tecnicamente possibile farlo.

PS. Nell'API Web ASP.NET è presente un altro filtro denominato filtro di autenticazione. L'idea è che tu lo usi per l'autenticazione e il filtro di autorizzazione per l'autorizzazione, come indica il nome. Tuttavia, ci sono molti esempi in cui questo confine è confuso. Molti esempi di filtri di autenticazione eseguiranno un qualche tipo di autenticazione. Ad ogni modo, se hai tempo e vuoi capire un po 'di più, dai un'occhiata a questo articolo di MSDN . Disclaimer: è stato scritto da me.


Grazie ancora, ma se leggo tra le righe, IsAuthenticated viene chiamato da OnAuthirization, quindi perché non sovrascrivere OnAuthorization e chiamare base.OnAuthorization e quindi controllare la risposta?
Royi Namir

Certo che puoi, se è quello che vuoi.
Badri

Nella mia terza domanda intendevo: dopo aver eseguito la funzione di base, ad esempio base.OnAuthorization, l'unico modo per verificare se ha avuto successo è ispezionare la proprietà Response ?, ps gli esempi provengono dal tuo libro :-)
Royi Namir

Sì, in genere cerchi il codice di stato 401 ma non nullo, per quanto ne so. A proposito, non ricordo di aver scritto sull'override OnAuthorizationnel mio libro. Sono sicuro che non avrei scritto sul controllo della risposta per null, perché è la prima volta che ne sento parlare :)
Badri

Sì, mi sono confuso con l'altro libro. Sto leggendo 3 libri contemporaneamente: securty (tuo), pratico (tuo) e webapi pro (Tugberk's, Zeitler, Ali). Come puoi vedere, l'hanno fatto lì: i.stack.imgur.com/LNGi4.jpg - hanno appena controllato se null, quindi dovrei controllare null o codici di errore?
Royi Namir

18

Ok, il mio suggerimento è di fare quanto segue supponendo che tu stia utilizzando i token di trasporto OAuth per proteggere la tua API Web e che tu stia impostando il allowTime come una rivendicazione per l'utente quando hai emesso il token. Puoi leggere ulteriori informazioni sull'autenticazione basata su token qui

  1. Crea CustomAuthorizeAttribute che deriva da AuthorizationFilterAttribute
  2. sostituire il metodo OnAuthorizationAsynce utilizzare il codice di esempio riportato di seguito:

     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. Ora nei tuoi controller usi l'attributo CustomAuthorize per proteggere i tuoi controller usando questa logica di autorizzazione.

1
Grazie. Ma attualmente sto usando AuthorizeAttributequale eredita AuthorizationFilterAttributee, anche per l'apprendimento, ho chiesto specificatamente quale metodo dovrei usare e sulla risposta ha contenuto o no ...
Royi Namir

3

ASP.NET v5 ha introdotto un sistema di autorizzazione completamente nuovo. Per coloro che utilizzeranno .NET 5, suggerirei di passare a Microsoft.AspNet.Authorization.

Praticamente avvolge il pasticcio causato da mantenere sia System.Web.Http.Authorizee System.Web.Mvc.Authorizeed altre implementazioni di autenticazione più anziani.

Fornisce un'ottima astrazione dei tipi di azione (creazione, lettura, aggiornamento, eliminazione), risorse, ruoli, attestazioni, visualizzazioni, requisiti personalizzati e consente di creare gestori personalizzati, combinando uno qualsiasi dei precedenti. Inoltre questi gestori possono essere utilizzati anche in combinazione.

In ASP.NET v5 l'autorizzazione fornisce ora un ruolo dichiarativo semplice e un modello basato su criteri più ricco in cui l'autorizzazione è espressa in requisiti e i gestori valutano le attestazioni degli utenti rispetto ai requisiti. I controlli imperativi possono essere basati su criteri o criteri semplici che valutano sia l'identità dell'utente che le proprietà della risorsa a cui l'utente sta tentando di accedere.


14
Buono a sapersi, ma non risponde affatto alla domanda.
Zero3
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.