В моем приложении (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 активируется первым.
Есть идеи?