2012-01-26 5 views
7

私はコントローラのアクションをAuthorizeAttributeでデコレートしています。MVC 3のAuthorizeAttributeでモデルデータを取得

[ServiceAuthorize(Roles="Editor,Publisher,Administrator")] 
public JsonResult Create(NewsArticle newsArticle) 

私は私のAuthorizeAttributeにOnAuthorize方法で使用したい私のNewsArticleモデルのフィールドがあります。

AuthorizeAttributeのOnAuthorizeメソッドからモデルにアクセスする方法はありますか?

私はそれがどこかでAuthorizationContext内で利用可能であると仮定しましたが、私はそれを見つけることができません。私はフィルタ属性のActionExecutingContextでそれを得ることができますが、それは私のアクションで別のフィルタが必要であることを意味し、すべての権限を1つの手順で実行できるようにしたいと考えています。

ありがとうございました。

答えて

6

AuthorizeAttributeのOnAuthorize メソッドからモデルを取得する方法はありますか?

モデルバインダーの前でOnAuthorizationが実行されているため、いいえです。あなたが行うことができますすることは値プロバイダーから値を読むことです:

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    var value = filterContext.Controller.ValueProvider.GetValue("someproperty"); 
    ... 
} 
+0

ありがとうダーリン。私は、私の場合、「物語」はおそらく「ニュース記事」だろうと思いますか?私はそれを確認します。 – Perry

+1

@Perry、いいえ、あなたは間違っていると思います。あなたの 'NewsArticle'クラスのプロパティになります。私が言ったように、' OnAuthorization'メソッドはモデルバインダーの前で実行されるので、この段階で 'NewsArticle'のインスタンスについて実際に話すことはできません。 ValueProviderが行う要求値を見ることができます。もちろん、彼らはこの段階で文字列の形を取るでしょう。追加の解析も必要になるかもしれません。 –

+0

説明をありがとう。 – Perry

1

私は基本的に一例として、アクションメソッドのパラメータの属性と許可を制御したい、同じことを達成しようとしていた。

[MyAuthorize] 
public ActionResult MyAction(
[Require(Permission.Write)] MyCustomObject arg1, 
[Require(Permission.Read)] MyCustomObject arg2 
) { 
    // ... all authorization would be handled before the action is invoked ... 
} 

class MyAuthorize : AuthorizeAttribute { 
    public override void OnAuthorization(AuthorizationContext filterContext) { 
     // ... filterContext doesn't have the argument objects ... 
    } 
} 

AuthorzeAttribute.OnAuthorization(...)を上書きすると、モデルバインドされた引数がまだ存在しません。同じ問題が発生しました。私が必要としたことを達成するために、IActionFilterを実装しました。このメソッドは、モデルがバインドされてからアクションが呼び出される前に呼び出されるメソッドOnActionExecutingを公開します。私のプロトタイプの実装は次のようになります:

class MyAuthorizeAttribute : AuthorizeAttribute, IActionFilter { 

    public override void OnAuthorization(AuthorizationContext filterContext) { 
     // ... I guesss this isn't really needed any more. 
     // the auth check is handled in OnActionExecuting. 
    } 

    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) { 

    } 

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) { 

     foreach (var param in filterContext.ActionDescriptor.GetParameters()) { 
      var attr = (RequireAttribute)param.GetCustomAttributes(typeof(RequireAttribute), false).FirstOrDefault(); 
      if(attr != null) { 
       Object obj; 
       if (filterContext.ActionParameters.TryGetValue(param.ParameterName, out obj)) { 
        var sec = obj as ISecurable; 
        if (sec == null || !sec.HasPermission(filterContext.RequestContext, attr.Permission)) { 
         filterContext.Result = new HttpStatusCodeResult(System.Net.HttpStatusCode.Unauthorized);         
        } 
       } 
      } 
     } 
    } 
} 

interface ISecurable { 
    bool HasPermission(Permission permission); 
} 

これは私が取り組んでいるプロジェクトの単なる立証ですが、実用的な解決策のようです。

関連する問題