我在旧版MVC5项目中有自定义AuthorizeAttribute
:
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
方法是显式调用还是从属性调用?我目前最好的是
Environment.StackTrace.Contains("at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters")
。
答案 0 :(得分:1)
您可以使用的一条路线是StackFrame。这比你现在的要干净一些。更多详情可在这找到: How can I find the method that called the current method
答案 1 :(得分: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
,因为您显然需要审核,而不是在这种情况下登录。