【问题标题】:Explain HOW the MVC Authorize Attribute performs AOP-like actions解释 MVC 授权属性如何执行类似 AOP 的操作
【发布时间】:2014-01-22 16:54:24
【问题描述】:

我一直试图弄清楚这在低级别是如何工作的:

[Authorize]
public ActionResult Index()
{
    return View();
}

基本上,上面的代码sn-p似乎拦截了对Index方法的调用,进行授权检查,如果没有授权就抛出异常。该异常会阻止调用 Index 方法中的代码。

这看起来很像 AOP,在 C# 中并不容易做到。如果我要实现我自己的扩展 System.Attribute 的类,我将没有任何接口来挂钩到我的属性装饰的方法的前调用或后调用。那么MVC的Authorize属性是怎么做的,我自己怎么做呢?

PostSharp 是一个使用 IL Weaving 完成相同任务的库。基本上,在编译时,PostSharp 会扫描程序集以查找使用某些属性修饰的方法,然后重新编写代码以将您的方法调用与其他方法调用包装起来。

MVC 框架是否也在编译时执行某种 IL Weaving?我可以进行自己的 IL Weaving 吗?或者是否有其他技术可以应用相同的 AOP 原则而无需复杂的 IL Weaving?

我试图查找有关 IL Weaving 的信息,但我找到的都是有关 PostSharp 的文章。由于许可问题,我宁愿远离 PostSharp,但此外,我只想知道他们是如何为我自己作为开发人员的成长而做的。这很迷人。

【问题讨论】:

  • 如果您还没有这样做,请获取 MVC 源代码。如果我记得,它没有 IL 编织那么复杂。框架只是在调用控制器方法之前执行动作方法属性。请求 -> 路由 -> 控制器选择 -> 获取相关动作方法 -> 执行相关属性 -> 执行动作方法。

标签: c# .net asp.net-mvc aop postsharp


【解决方案1】:

了解它的最简单方法是查看源代码。

一个基本的解释是 mvc 控制器不像 instance.method 那样简单地调用(在这种情况下,你需要 postsharp 使属性以相同的方式工作)

有一个ControllerActionInvoker 其中有方法

 public virtual bool InvokeAction(ControllerContext controllerContext, string actionName)
 {
    ...
    // get all the filters (all that inherit FilterAttribute), inlcuding the authorize attribute
    FilterInfo filterInfo = GetFilters(controllerContext, actionDescriptor); 

首先所有继承IAuthorizationFilter的过滤器都执行(Authorize, ValidateAntiForgeryToken),如果验证成功则其余的都执行

AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
    //authContext.Result has value if authorization didn't succeed
if (authContext.Result != null)
{
    // the auth filter signaled that we should let it short-circuit the request
    InvokeActionResult(controllerContext, authContext.Result);
}
else
{
    if (controllerContext.Controller.ValidateRequest)
    {
        ValidateRequest(controllerContext);
    }

    IDictionary<string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);

    //invoke the action with filters here
    ActionExecutedContext postActionContext = InvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters);
    InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
}

【讨论】:

  • 不错。它是虚拟的,因此如果我们想添加其他类型的基于属性的过滤器,这些过滤器与授权无关(例如日志记录),我们可以对其进行扩展。因此,如果没有 PostSharp 或滚动我们自己的 IL Weaver,就无法像往常一样自动将类似 AOP 的属性添加到任何随机类并调用方法。这是有道理的。
  • 您不必重写它来添加其他过滤器:asp.net/mvc/tutorials/hands-on-labs/…
  • 我想如果我想让我的自定义属性约束我的非控制器方法(如过滤器)将非常困难..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多