2016-06-03 33 views
7

Ho un personalizzato AuthorizeAttribute in un progetto legacy MVC5:rilevare se AuthorizationAttribute chiamato manualmente

public class AuthorizeWithLoggingAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (!base.AuthorizeCore(httpContext)) {Log(FilterContext);} 
    } 
} 

Abbiamo notato mentre guardando attraverso i registri, che oltre ad essere ad applicare ai controllori con [AuthorizeWithLogging], veniva chiamato esplicitamente in altre parti del codice, che generano i registri spurie:

var filters = new FilterInfo(FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor)); 
foreach (var authFilter in filters.AuthorizationFilters) 
{ 
    authFilter.OnAuthorization(authContext); 
    if (authContext.Result != null) {return false;} 
} 

c'è un modo di dire (via StackTrace o qualcosa) se il metodo OnAuthorization è essere esplicitamente calle d, o chiamato dall'attributo? Il migliore che attualmente ho è Environment.StackTrace.Contains("at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters").

+0

Perché non trovi tutti i riferimenti al metodo "OnAuthorization' di" AuthorizeAttribute "nel tuo codice? –

+0

Quale versione MVC stai usando? –

+0

@AmateurProgrammer che ho fatto. Sono difficili da rimuovere. Se potessimo fare tutto da capo, lo faremmo diversamente. – Arithmomaniac

risposta

1

AuthorizeAttribute ha una sola responsabilità: determinare se l'utente è autorizzato o meno. Questo può essere utilizzato in più punti dell'applicazione per svariati motivi.

Qualsiasi azione eseguita come non autorizzata (ad esempio la restituzione di una risposta HTTP 401) viene delegata a un gestore di tipo ActionResult impostato sulla proprietà AuthorizationContext.Result. Ad esempio, qui è l'implementazione predefinita di AuthorizeAttribute.HandleUnauthorizedRequest:

protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
{ 
    // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs. 
    filterContext.Result = new HttpUnauthorizedResult(); 
} 

Se si sta tentando di fare auditing quando un utente non è autorizzato, si dovrebbe mettere la revisione contabile nel gestore ActionResult, non è nel costume AuthorizeAttribute. Ciò garantisce che il controllo venga eseguito solo se viene eseguito ActionResult (ovvero, quando la pagina corrente non è autorizzata), non in ogni caso viene verificata l'autorizzazione.

public class AuthorizeWithLoggingAttribute : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     filterContext.Result = new LoggingActionResult(new HttpUnauthorizedResult(), filterContext); 
    } 
} 

public class LoggingActionResult : ActionResult 
{ 
    private readonly ActionResult innerActionResult; 
    private readonly AuthorizationContext filterContext; 

    public LoggingActionResult(ActionResult innerActionResult, AuthorizationContext filterContext) 
    { 
     if (innerActionResult == null) 
      throw new ArgumentNullException("innerActionResult"); 
     if (filterContext == null) 
      throw new ArgumentNullException("filterContext"); 

     this.innerActionResult = innerActionResult; 
     this.filterContext = filterContext; 
    } 

    public override void ExecuteResult(ControllerContext context) 
    { 
     // Do logging (or apparently you want auditing) here 
     Log(this.filterContext); 

     innerActionResult.ExecuteResult(context); 
    } 
} 

NOTA: Vorrei nominarli AuthorizeWithAuditingAttribute e AuditingActionResult poiché si desidera chiaramente di revisione, non accedendo in questo caso.