2012-04-30 19 views
7

私は、MVC 3アプリケーションのコントローラでアクションメソッドをデコレートする可能性のあるすべての認証属性を調べようとしています。基本的にActionLinkのラッパーである私自身のHtmlHelper拡張メソッドでこれをやっています(実行時に利用可能な情報のコンテキストを提供するため)。私は基本的な解決策を用意していますが、オーバーロードされたメソッドではそれが爆発的になりました。私はフレームワークが内部的にURLをアクションメソッドに解決していることを知っていますが、System.Web.Mvc.LinkExtensionsのコードを見ても、どういうことが起こっているのかまだ分かりません。この問題に取り組む。要求されたアクションメソッドの属性を取得する方法

private static bool _IsUserAuthorized(HtmlHelper html, 
    string controllerName, string actionName) 
{ 
    controllerName = controllerName ?? 
    html.ViewContext.RouteData.GetRequiredString("controller"); 

    var factory = ControllerBuilder.Current.GetControllerFactory(); 
    var controller = factory.CreateController(
    html.ViewContext.RequestContext, controllerName); 

    Type controllerType = controller.GetType(); 
    var methodInfo = controllerType.GetMethod(actionName, 
    BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); 

    ... check authentication 
} 

だから私の現在の問題は、メソッドがオーバーライドされたときに、私が得ることである「あいまいな一致が見つかった」例外:

はここで、これまでの関連する方法を解決するための私が持っているコードです。私はRouteValuesを処理してメソッドへのパラメータを解決する必要があると思いますので、正しい値を明白に識別できます。誰にどのようにこれを行うにはいくつかのポインターがありますか?あるいは、フレームワークはすでに必要な正確な方法を解決する手段を提供していますか?

ありがとうございます!

+0

OKを取得しますので、私はMVC3のソースコードに掘り守ってきたと私はControllerDescriptorインスタンスおよび使用を取得する必要がありますように見える書いたメソッドをコピーしました適切なアクションメソッドのActionDescriptorを取得します。その場合、要求されたアクションメソッドがHtmlHelper.ViewContext.Controllerのコントローラでない場合、適切なコントローラのControllerContextを取得するにはどうすればよいですか? –

+0

ControllerContextを取得することはかなり簡単です。 ControllerDescriptorを取得する。何かご意見は? –

+0

ControllerDescriptorとActionDescriptorを取得するためのコード[here](http://weblogs.asp.net/jeffreyzhao/archive/2009/01/30/extend-asp-net-mvc-for-asynchronous-action.aspx)が見つかりました。近づく... –

答えて

2

EDIT:this pageのインサイトを含むようにメソッドを更新しました。この最終バージョンでは、要求されたアクションメソッドのAuthorizationFiltersが表示され、ユーザーがアクションを実行する権限を持っているかどうかがチェックされます。

私はSystem.Web.Mvc.ControllerActionInvokerを掘り出し、必要なメソッドとコンストラクタを見つけました。 ControllerDescriptor.FindAction()がキーになりました。以下は、私はそれが すべての属性

private static bool _IsUserAuthorized(HtmlHelper htmlHelper, 
    string controllerName, string actionName) 
{ 
    ControllerContext controllerContext = null; 
    //if controllerName is null or empty, we'll use the 
    // current controller in HtmlHelper.ViewContext. 
    if (string.IsNullOrEmpty(controllerName)) 
    { 
    controllerContext = htmlHelper.ViewContext.Controller.ControllerContext; 
    } 
    else //use the controller factory to get the requested controller 
    { 
    var factory = ControllerBuilder.Current.GetControllerFactory(); 
    ControllerBase controller = (ControllerBase)factory.CreateController(
     htmlHelper.ViewContext.RequestContext, controllerName); 
    controllerContext = new ControllerContext(
     htmlHelper.ViewContext.RequestContext, controller); 
    } 

    Type controllerType = controllerContext.Controller.GetType(); 
    ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerType); 
    ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName); 
    if (actionDescriptor == null) 
    return false; 

    FilterInfo filters = new FilterInfo(FilterProviders.Providers.GetFilters(
    controllerContext, actionDescriptor)); 

    AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor); 
    foreach (IAuthorizationFilter authFilter in filters.AuthorizationFilters) 
    { 
    authFilter.OnAuthorization(authContext); 
    if (authContext.Result != null) 
     return false; 
    } 
    return true; 
} 
0

承認コードを追加する通常の方法は、Authorization Filterです。

IAuthorizationFilter.OnAuthorizationは、ActionDescriptorプロパティを持つAuthorizationContextオブジェクトを提供します。

+0

私は既に認可フィルタを使用していますが、私がそれを紛失していない限り、フレームワークはアクションを呼び出す前に認可を調べる手段を提供しません。私は、リンクされているアクションを実行するアクセス権を持たないユーザーからのリンクを隠そうとしているので、htmlをレンダリングする前に認可属性を調べる必要があります。 OnAuthorizationの処理は、私が必要とする機能のためにチェーンで遅すぎるでしょう。 –

関連する問題