Объясните, КАК атрибут авторизации MVC выполняет действия, подобные АОП

Я пытался понять, как это работает на низком уровне:

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

По сути, приведенный выше фрагмент кода, кажется, перехватывает вызовы метода Index, выполняет проверку авторизации и генерирует исключение, если не авторизован. Исключение предотвращает вызов кода в методе Index.

Это кажется очень похожим на АОП, и это нелегко сделать на C #. Если бы я реализовал свой собственный класс, расширяющий System.Attribute, у меня не было бы никакого интерфейса, который можно было бы подключать к предварительному или последующему вызову метода, который украшает мой атрибут. Итак, как это делает атрибут авторизации MVC и как я могу сделать это самостоятельно?

PostSharp - это библиотека, которая выполняет то же самое с помощью IL Weaving. По сути, во время компиляции PostSharp сканирует сборку на предмет методов, украшенных определенными атрибутами, а затем повторно записывает ваш код, чтобы обернуть вызовы ваших методов вызовами других методов.

Фреймворк MVC также выполняет какое-то переплетение IL во время компиляции? Могу ли я выполнить собственное плетение IL? Или есть другие методы для применения тех же принципов АОП без сложного плетения IL?

Я пытался найти информацию о IL Weaving, но все, что я нашел, это статьи о PostSharp. Я бы предпочел держаться подальше от PostSharp из-за проблем с лицензированием, но, более того, я просто хочу знать, как, черт возьми, они это сделали для моего собственного роста как разработчика. Это довольно увлекательно.


person Michael    schedule 22.01.2014    source источник
comment
Если вы еще этого не сделали, возьмите исходный код MVC. Насколько я помню, нет ничего более сложного, чем IL-плетение; структура просто выполняет атрибуты метода действия перед вызовом метода контроллера. Запрос - ›маршрутизация -› выбор контроллера - ›получение соответствующего метода действия -› выполнение соответствующих атрибутов - ›выполнение метода действия.   -  person Tim Medora    schedule 22.01.2014


Ответы (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);
}
person Omu    schedule 22.01.2014
comment
Хороший. И он виртуальный, поэтому мы можем расширить его, если захотим добавить другие типы фильтров на основе атрибутов, которые не имеют отношения к авторизации (например, ведение журнала). Таким образом, без PostSharp или развертывания нашего собственного IL Weaver невозможно автоматически добавлять AOP-подобные атрибуты к любому случайному классу и вызывать методы, как обычно. В этом есть смысл. - person Michael; 22.01.2014
comment
вам не нужно переопределять его, чтобы добавить другие фильтры: asp.net/mvc/tutorials/hands-on-labs/ - person Omu; 22.01.2014
comment
Думаю, будет очень сложно, если я захочу, чтобы мой настраиваемый атрибут ограничивал мой неконтроллерный метод, такой как filter .. - person Yiping; 10.05.2016