在OnAuthorization之前执行的ASP.NET MVC Global或BaseController ActionFilter

时间:2011-09-15 16:27:06

标签: c# asp.net-mvc authorization actionfilterattribute authorize-attribute

在我的应用程序(ASP.NET MVC 3)中,我有一个BaseController类,我的所有控制器继承,并且在该BaseController中我已经重写了OnActionExecuting方法以检查以确保填充了Session变量,因为我需要访问所有应用程序中的其他操作方法。我还有一个我定义的自定义Authorize属性,它扩展了AuthorizeAttributeClass。在该属性中,我重写OnAuthorization以检查我在BaseController OnActionExecuting方法中加载的相同Session变量,以查看是否应该允许用户继续。

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方法在我的AuthorizeByPermission属性中的OnAuthorization方法之后触发,我需要它是另一种方式arround,因为BaseController需要在Session变量之前不存在,如果它不存在于authorize属性之前尝试访问它。

基本上我需要找到一种方法来使用基类方法或全局过滤器,可以在OnAuthorization方法触发之前注册。关于如何做到这一点的任何想法?

我已经尝试注册一个GlobalFilter来加载会话变量,并将其Order属性设置为低于AuthorizeByPermission属性,但这似乎也不起作用。

我还尝试覆盖BaseController中的Execute方法,并且在自定义授权属性之前实际触发但问题是我无法访问filterContext,这允许我将用户重定向到SignIn页面无法加载会话变量。

根据bmosh的评论,我尝试将我的BaseController OnActionExecuting方法转换为单独的过滤器,并使用比AuthorizeByPermission属性更低的Order编号来装饰BaseController,但它仍然不起作用。

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

}

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

即使使用上述设置,也会首先触发AuthorizeByPermission属性。

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

您可以尝试在基本控制器中重写OnAuthorization而不是OnActionExecuting。