ASP.NET MVC Global или BaseController ActionFilter для выполнения перед авторизацией

В моем приложении (ASP.NET MVC 3) у меня есть класс BaseController, который наследуют все мои контроллеры, и в этом BaseController я переопределил метод OnActionExecuting, чтобы проверить чтобы обеспечить заполнение переменной сеанса, поскольку мне нужен доступ к ней во всех других методах действий в приложении. У меня также есть настраиваемый атрибут авторизации, который я определил, который расширяет класс AuthorizeAttributeClass. В этом атрибуте я переопределяю OnAuthorization, чтобы проверить ту же переменную сеанса, которую я загружаю в метод BaseController OnActionExecuting, чтобы узнать, следует ли пользователю разрешить продолжить.

BaseController

public class BaseController : Controller
{
    private ISessionUserService sessionUserService;

    public BaseController(ISessionUserService sessionUserService)
    {
        this.sessionUserService = sessionUserService;            
    }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);

        if (User != null && User.Identity.IsAuthenticated && this.sessionUserService.Current == null)
        {                     
            this.sessionUserService.Start(accountID, User.Identity.Name);                                                                           

            // If we weren't successful in reloading the SessionUser
            // variable, redirect the user to the Sign In view
            if (this.sessionUserService.Current == null)
            {                  
                filterContext.Result = new RedirectResult(Url.Action("SignIn", "Access", new { area = string.Empty }));
                return;
            }
        }
    }

}

Пользовательский атрибут авторизации

public class AuthorizeByPermission : AuthorizeAttribute
{        
    public Permission[] Permissions { get; set; }

    public AuthorizeByPermission(params Permission[] permissions)
    {
        this.Permissions = permissions;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        SessionUser sessionUser = filterContext.HttpContext.Session.Get<SessionUser>();

        if (sessionUser.HasPermission(Permissions))
            return;

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

Проблема в том, что метод BaseController OnActionExecuting запускается ПОСЛЕ метода OnAuthorization в моем атрибуте AuthorizeByPermission, и мне нужно, чтобы это было наоборот, поскольку BaseController необходимо заполнить переменную сеанса если его нет до того, как атрибут авторизации попытается получить к нему доступ.

В основном мне нужно найти способ иметь метод базового класса или глобальный фильтр, который может быть зарегистрирован до срабатывания метода OnAuthorization. Есть идеи, как это сделать?

Я попытался зарегистрировать GlobalFilter для загрузки переменной сеанса и установить для его свойства Order значение ниже атрибута AuthorizeByPermission, но это тоже не сработало.

Я также попытался переопределить метод Execute в BaseController, который фактически запускался перед настраиваемым атрибутом авторизации, но проблема заключалась в том, что у меня не было доступа к filterContext, который позволял мне перенаправить пользователя на страницу входа, если мы не удалось загрузить переменную сеанса.

В соответствии с комментарием bmosh я попытался превратить мой метод BaseController OnActionExecuting в отдельный фильтр и украсить BaseController этим атрибутом с более низким порядковым номером, чем атрибут AuthorizeByPermission, но это все равно не сработало.

[FilterIWantToFireFirst(Order = 1)]
public class BaseController : Controller
{

}

public class AnotherController : BaseController
{
     [AuthorizeByPermission(Permission.Add, Order = 2)]
     public ActionResult SomeActionMethod() 
     {
     }
}

Даже при описанной выше настройке атрибут AuthorizeByPermission активируется первым.

Есть идеи?

5
задан Nick Olsen 15 September 2011 в 17:32
поделиться