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

发布于 2024-12-04 22:28:43 字数 3010 浏览 1 评论 0原文

在我的应用程序(ASP.NET MVC 3)中,我有一个 BaseController 类,我的所有控制器都继承该类,并且在该 BaseController 中,我重写了 OnActionExecuting 方法来检查以确保填充 Session 变量,因为我需要在所有其他操作方法中访问该变量在应用程序中。我还定义了一个扩展 AuthorizeAttributeClass 的自定义 Authorize 属性。在该属性中,我重写 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 方法在我的 AuthorizeByPermission 属性中的 OnAuthorization 方法之后触发,我需要它是另一种方式,因为 BaseController 需要填充 Session 变量(如果它在授权之前不存在)属性尝试访问它。

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

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

我还尝试重写 BaseController 中的 Execute 方法,该方法实际上在自定义授权属性之前触发,但问题是我无权访问 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 属性也会首先被触发。

有什么想法吗?

In my application (ASP.NET MVC 3) I have a BaseController class that all my Controllers inherit and in that BaseController I have overridden the OnActionExecuting method to check to ensure a Session variable is populated as I need access to that in all other action methods in the application. I also have a custom Authorize attribute that I have defined that extends the AuthorizeAttributeClass. In that attribute I override OnAuthorization to check the same Session variable I am loading in the BaseController OnActionExecuting method to see if the user should be permitted to continue.

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

}

Custom Authorize Attribute

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

The problem is that the BaseController OnActionExecuting method is firing AFTER the OnAuthorization method in my AuthorizeByPermission attribute and I need it to be the other way arround as the BaseController needs to popualte the Session variable if it isn't there before the authorize attribute attempts to access it.

Basically I need to find a way to have a base class method or a global filter that can be registered to occur before the OnAuthorization method fires. Any ideas on how to do this?

I have tried registering a GlobalFilter to load the session variable and set its Order property to be lower than the AuthorizeByPermission attribute but that didn't seem to work either.

I have also tried overriding the Execute method in the BaseController and that actually fired before the custom authorization attribute but the problem was that I didn't have access to the filterContext which allowed me to redirect the user to the SignIn page if we couldn't load the session variable.

As per bmosh's comment I tried turning my BaseController OnActionExecuting method into a separate filter and decorate the BaseController with that attribute with a lower Order number than the AuthorizeByPermission attribute but it still didn't work.

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

}

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

Even with the above setup, the AuthorizeByPermission attribute is fired first.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

潇烟暮雨 2024-12-11 22:28:43

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

You could try overriding OnAuthorization instead of OnActionExecuting in your base controller.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文