2016-06-03 3 views
7

У меня есть обычай AuthorizeAttribute в проекте наследие MVC5:Detecting если AuthorizationAttribute вручную называется

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

Мы заметили, глядя через журналы, что в дополнение к тому, чтобы применять к контроллерам с [AuthorizeWithLogging], он вызывается явно в другом месте в коде, порождающие ложные журналы:

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

есть ли способ сказать (через StackTrace или что-то) ли быть явно метод OnAuthorization Каллы d или вызван из атрибута? Лучшее, что у меня сейчас есть, - Environment.StackTrace.Contains("at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters").

+0

Почему бы вам не найти все ссылки на метод 'OnAuthorization'' AuthorizeAttribute' в вашем коде? –

+0

Какую версию MVC вы используете? –

+0

@ AmateurProgrammer я сделал. Их трудно выбить. Если бы мы могли сделать это снова, мы бы сделали это по-другому. – Arithmomaniac

ответ

1

AuthorizeAttribute несет отдельную ответственность: определить, разрешен ли пользователь. Это может использоваться в нескольких местах приложения по разным причинам.

Любые действия, предпринятые в результате не авторизации (например, возврат ответа HTTP 401), делегируются обработчику типа ActionResult, который установлен в свойство AuthorizationContext.Result. Например, вот реализация по умолчанию AuthorizeAttribute.HandleUnauthorizedRequest:

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

Если вы пытаетесь сделать аудит, когда пользователь не авторизован, то вы должны поставить аудит в ActionResult обработчика, а не в обычае AuthorizeAttribute. Это гарантирует, что аудит выполняется только в том случае, если выполняется ActionResult (то есть, когда текущая страница не авторизована), а не во всех случаях проверяется авторизация.

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

Примечание: Я бы назвал их AuthorizeWithAuditingAttribute и AuditingActionResult, так как вы хотите четко аудита, не войдя в данном случае.