2013-04-17 4 views
12

私はAsp.Net Web APIから始まり、ここに私の問題があります:Asp.net Web API承認フィルタでは、どのようにパラメータにアクセスできますか?

APIキーを探して私のメッセージヘッダーを調べるカスタム認証フィルターを実装します。このAPIキーに基づいて、私は自分のユーザーを取得し、彼がいくつかのリソースにアクセスできるかどうかを確認したいと思います。確認したいリソースIDは、HTTPリクエストのパラメータに基づいています。しかし、私はAuthorizationFilterメソッドで、アクションパラメーターのリストは空です。

どうすればいいですか?

認可フィルタの代わりにActionFilterを使用した場合、これが最初に実行されるフィルタであることをどのように確認できますか?また、グローバルに、フィルタの実行順序を指定するにはどうすればよいですか?

最後の質問は、私が任意のフィルタで取得できる "パイプ上の"データを追加することは可能ですか?セッションストアのようなものですが、リクエストに限定されていますか?認可が結合パラメータの前に実行属性任意の応答

答えて

23

ため

おかげでActionArgumentsコレクションを使用します(あなたが見てきたように)あなたができないため、実行されました。代わりに、以下に示すように、クエリパラメータにuriリクエストを使用し、uriパラメータにデータをルーティングする必要があります。実行順序について

//request at http://localhost/api/foo/id?MyValue=1 
public class MyAuthorizationAttribute : AuthorizeAttribute 
{ 
    protected override bool IsAuthorized(HttpActionContext actionContext) 
    { 
     //will not work as parameter binding has not yet run 
     object value; 
     actionContext.ActionArguments.TryGetValue("id", out value); 

     //Will get you the resource id assuming a default route like /api/foo/{id} 
     var routeData = actionContext.Request.GetRouteData(); 
     var myId = routeData.Values["id"] as string; 

     //uri is still accessible so use this to get query params 
     var queryString = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query); 
     var myQueryParam = queryString["MyValue"]; 

     //and so on 
    } 
} 

FilterScope Enumeration ...範囲であることグローバル、コントローラとアクションを使用して、フィルタの実行順序を指定する3種類の方法があります。 AuthoriseAttributeは「グローバル」なので、

コントローラの前にアクションを指定します。

あなたはこれらの3つのスコープ内の実行順序を指定するために必要な場合は、パイプにいくつかのデータを追加するにはFilterProvider

を実装する必要がありますどこあなたがここにthis blog articleをお読みください:

要求の期間中、このコレクションが利用可能である要求に対してプロパティコレクションを使用します。パラメータのバインディングExecuteにパラメータを取得する

protected override bool IsAuthorized(HttpActionContext actionContext) 
    { 
     actionContext.Request.Properties.Add("__MYKEY__","MyValue"); 

     //access this later in the controller or other action filters using 
     var value = actionContext.Request.Properties["__MYKEY__"]; 

    } 
+0

RouteDataからパスパラメータ情報を取得することもできます。メモリが私に役立つなら、Request.GetRouteData()のようなものになります。 –

+0

@DarrelMiller、私はちょうどそのアイデアをフォローし、私のハーネスはそのように動作していないようです。 var routeData = actionContext.Request.GetRouteData(); var value = routeData.Values ["MyValue"]を文字列として返します。私のrouteDataにはコントローラの値しか入っていません。あなたが同意しない場合、私はさらに調査します。 –

+0

最初に、要求のプロパティに値を設定した承認フィルターを使用してから、アクションフィルターが機能しています。他の情報も有用でした。ご協力いただきありがとうございます。 – Ben

1

もう一つの選択肢です。

try 
{ 
    var binding = actionContext.ActionDescriptor.ActionBinding; 
    var parameters = binding.ParameterBindings.OfType<ModelBinderParameterBinding>(); 
    var newBinding = new HttpActionBinding(actionContext.ActionDescriptor, parameters.ToArray()); 
    newBinding.ExecuteBindingAsync(actionContext, new CancellationToken()); 
    var id = actionContext.ActionArguments["id"] as string; 
} 
catch 
{ 
    base.HandleUnauthorizedRequest(actionContext); 
} 

注:あなたは、私がリクエストから来ることが予想されているすべてのパラメータのバインディングを実行していることに気づいて、あなただけのリクエストURIから来るのパラメータでフィルタを確認する必要があり身体は実際の行動に引き継がれなくなります。すなわちそれらのパラメータはヌルになります。

です。GetRouteData()/RouteDataを使用することをお勧めします。これは、ASP.NET MVCモデルバインドのさらなる流れを妨害しない可能性が高いためです。

var routeData = actionContext.ControllerContext.RouteData; 
var id = routeData.Values["id"] as string; 
関連する問題