解释MVC授权属性如何执行类似AOP的操作

时间:2014-01-22 16:54:24

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

我一直试图弄清楚它是如何在低级别上运作的:

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

基本上,上面的代码片段似乎拦截了对Index方法的调用,执行了授权检查,并且如果未经授权则抛出异常。该异常可防止调用Index方法中的代码。

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

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

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

我试图找到关于IL编织的信息,但我找到的只是关于PostSharp的文章。由于许可麻烦,我宁愿远离PostSharp,而且,我只是想知道他们为我自己作为开发人员的成长做了多少。这真是令人着迷。

1 个答案:

答案 0 :(得分:6)

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

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

有一个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),如果auth成功完成其余的

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