2012-07-15 5 views
7

私はMVC 4で独自のカスタム許可属性を実装しており、AuthorizeAttributeクラスを継承しています。私もカスタムActionFilterAttributeを持っています。これらはどちらもうまくいきますが、問題はそれらを順序づけることにあります。カスタム認証フィルターの前に実行するカスタムアクションフィルターが必要です。アクションの実行方法承認フィルタ前のフィルタMVC 4

私は属性にOrderプロパティを使用しようとしましたが、私が理解するように、権限フィルタは常にアクションフィルタの前に実行されます。

承認フィルターの前にアクションフィルターを強制的に実行する方法を知っている人はいますか?

+0

Authorize Filterは、ユーザーに許可があるかどうかをチェックし、許可されていない場合は何もチェックしません。奇妙なことをしているように聞こえる。たぶんあなたがそれらを交換したい理由を説明してください。 –

+0

さて、アクションフィルタは、特定のユーザが一時的なパスワードを持っているかどうかをチェックするので、「パスワードの変更」ページにリダイレクトされ、「許可されていません。うまくいくと思います... – davey1990

+1

一時的なパスワードを持つ人がAuthorizeチェックに失敗するように思えますが、一時パスワードを持っている場合は「Unauthorized」ページをチェックして、その場合は「パスワードの変更」ページを開きます。また、ログイン時にこれをキャッチして、ログインを許可する前にパスワードを変更するように強制することもできます。それで、心配する必要はありません。 –

答えて

10

ソースコード(http://aspnetwebstack.codeplex.com/で利用可能)を見ると、これは標準のフィルタークラスでは不可能であることがわかります。 IAuthorizationFilterの実装は、IActionFilterの実装より前に常に実行されます。認可フィルタが結果を返すとき、アクションフィルタは実行されないからです。カスタムControllerFactoryクラスであなたのコントローラにカスタムMyControllerActionInvokerクラスを注入する必要が

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

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; 
    } 
} 
をあなた自身 ControllerActionInvoker子孫クラスを作成し、 InvokeActionメソッドをオーバーライドすることができ、これを解決するために

もちろん、自分でMyControllerFactoryをMVCフレームワークに登録する必要があります。

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

この実装はここで問題なく動作します。

関連する問題