2016-06-03 25 views
7

Ich habe eine benutzerdefinierte AuthorizeAttribute in einem Legacy-MVC5 Projekt:Detecting wenn AuthorizationAttribute manuell aufgerufen

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

Wir haben festgestellt, während durch die Protokolle suchen, dass zusätzlich zu den auf mit [AuthorizeWithLogging] an Steuerungen angewandt werden können, es genannt wurde ausdrücklich an anderer Stelle im Code, Erzeugen von falschen Protokolle:

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

gibt es eine Möglichkeit (über StackTrace oder etwas) zu sagen, ob die OnAuthorization Methode explizit calle sein d, oder von dem Attribut aufgerufen? Die beste, die ich derzeit habe, ist Environment.StackTrace.Contains("at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters").

+0

Warum finden Sie in Ihrem Code nicht alle Verweise auf die 'OnAuthorization'-Methode von' AuthorizeAttribute'? –

+0

Welche MVC-Version verwenden Sie? –

+0

@AmateurProgrammierer tat ich. Sie sind schwer zu entfernen. Wenn wir alles noch einmal machen könnten, würden wir es anders machen. – Arithmomaniac

Antwort

1

AuthorizeAttribute hat eine einzige Verantwortung: um zu bestimmen, ob der Benutzer berechtigt ist. Dies kann aus verschiedenen Gründen an mehreren Stellen in der Anwendung verwendet werden.

Alle Aktionen, die ausgeführt werden, wenn sie nicht autorisiert sind (z. B. das Zurücksenden einer HTTP 401-Antwort), werden an einen Handler des Typs ActionResult delegiert, der auf die Eigenschaft AuthorizationContext.Result festgelegt ist. Zum Beispiel, hier ist die Standardimplementierung von AuthorizeAttribute.HandleUnauthorizedRequest:

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

Wenn Sie versuchen, Rechnungsprüfung zu tun, wenn ein Benutzer nicht autorisiert ist, sollten Sie die Prüfung in die ActionResult Handler setzen, nicht in den benutzerdefinierten AuthorizeAttribute. Dies stellt sicher, dass die Überwachung nur ausgeführt wird, wenn die ActionResult ausgeführt wird (dh wenn die aktuelle Seite nicht autorisiert ist), nicht in jedem Fall wird die Autorisierung geprüft.

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

HINWEIS: Ich würde sie AuthorizeWithAuditingAttribute und AuditingActionResult nennen, da Sie eindeutig Auditierung wollen, in diesem Fall nicht anzumelden.