【问题标题】:How to execute Action Filter before Authorization Filter MVC 4如何在授权过滤器 MVC 4 之前执行操作过滤器
【发布时间】:2012-07-14 20:14:29
【问题描述】:

我通过继承AuthorizeAttribute 类在 MVC 4 中实现了我自己的自定义授权属性。我还有一个自定义的ActionFilterAttribute。这些都可以正常工作,但问题在于订购它们。我需要在自定义授权过滤器之前运行自定义操作过滤器。

我曾尝试将Order 属性用于属性,但据我了解,授权过滤器将始终在操作过滤器之前运行。

有谁知道如何强制动作过滤器在授权过滤器之前执行??

【问题讨论】:

  • 授权过滤器检查用户是否有权限,如果没有权限,则检查其他任何内容都没有意义。听起来你在做一些奇怪的事情。或许可以解释一下为什么要交换它们。
  • 好吧,操作过滤器会检查特定用户是否有临时密码,所以我希望他们在出现“未授权”之前被重定向到“更改密码”页面。希望这是有道理的......
  • 在这种情况下,听起来您希望拥有临时密码的人仍然无法通过授权检查,但只是想检查您的“未经授权”页面(如果他们有临时密码),然后重定向到“在这种情况下更改密码”页面。或者,您可以在登录时捕捉到这一点,并在您允许他们登录之前强制他们更改密码。那你就不用担心了。

标签: asp.net-mvc-4 custom-attributes


【解决方案1】:

当您查看源代码(可在http://aspnetwebstack.codeplex.com/ 获得)时,您会发现标准过滤器类无法做到这一点。 IAuthorizationFilter 实现总是在 IActionFilter 实现之前执行。这是因为当授权过滤器返回结果时,操作过滤器不会运行。

要解决这个问题,您可以创建自己的 ControllerActionInvoker 后代类并覆盖 InvokeAction 方法:

public class MyControllerActionInvoker : ControllerActionInvoker
{
    public override bool InvokeAction(ControllerContext controllerContext, string actionName)
    {
        // Your initialization code here
        try
        {
            return base.InvokeAction(controllerContext, actionName);
        }
        finally
        {
            // Your finalization code here
        }
    }
}

您需要将自定义 MyControllerActionInvoker 类注入到您的控制器中的自定义 ControllerFactory 类中:

public class MyControllerFactory : DefaultControllerFactory
{
    private readonly MyControllerActionInvoker actionInvoker = new MyControllerActionInvoker();

    /// <summary>
    /// Retrieves the controller instance for the specified request context and controller type.
    /// </summary>
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        var controllerInstance = base.GetControllerInstance(requestContext, controllerType);

        if (controllerInstance != null)
        {
            var typedController = controllerInstance as Controller;
            if (typedController != null)
            {
                typedController.ActionInvoker = this.actionInvoker;
            }
        }

        return controllerInstance;
    }
}

当然,您现在必须在 MVC 框架中注册自己的 MyControllerFactory。您应该在同时注册路线的地方执行此操作:

var controllerFactory = new MyControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory);

这个实现在这里运行良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-27
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    相关资源
    最近更新 更多