2013-04-17 3 views
12

Ich bin mit Asp.Net Web API gestartet und hier ist mein Problem:Auf Asp.net Web API Autorisierungsfilter, wie kann ich auf Parameter zugreifen?

Ich implementiere einen benutzerdefinierten Autorisierungsfilter, um meine Nachrichtenkopfzeile auf der Suche nach einem API-Schlüssel zu überprüfen. Basierend auf diesem API-Schlüssel, lade ich meinen Benutzer ab und dann würde ich gerne sehen, ob er Zugriff auf einige Ressourcen haben kann. Die Ressourcen ID, die ich überprüfen möchte, ist auf den Parametern der HTTP-Anfrage. Aber wenn ich in der AuthorizationFilter-Methode bin, ist die Liste der Aktionsparameter leer.

Wie kann ich das tun?

Wenn ich einen ActionFilter als Ersatz für einen Autorisierungsfilter verwendet habe, wie kann ich sicher sein, dass dies der erste ausgeführte Filter ist? Und global, wie kann ich die Ausführungsreihenfolge von Filtern angeben?

Letzte Frage, ist es möglich, einige Daten "auf der Rohrleitung" hinzuzufügen, die ich auf jedem Filter abrufen konnte? So etwas wie ein Session-Store, aber auf die Anfrage beschränkt?

Vielen Dank für jede Antwort

Antwort

23

Die Berechtigung laufen Attribute, bevor Parameter daher ausgeführt wurde Bindung können Sie nicht verwenden (wie Sie gesehen haben), um die ActionArguments Sammlung. Stattdessen müssen Sie die Anfrage-URL für Abfrageparameter und Routendaten für URI-Parameter verwenden, wie unten gezeigt.

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

über die Ausführungsreihenfolge:

Es gibt 3 verschiedene Möglichkeiten, die Ausführungsreihenfolge von Filtern Angabe der FilterScope Enumeration ... Umfang sein Global, Steuerung und Aktion verwendet wird. Der AuthoriseAttribute ist "Global" und daher

Gibt eine Aktion vor dem Controller an.

Wenn Sie benötigen, um die Ausführungsreihenfolge innerhalb dieser drei Bereiche angeben, dann sollten Sie this blog article hier lesen, wo Sie ein FilterProvider

implementieren müssen, um einige Daten zu dem Rohr hinzufügen:

Verwenden Sie die Eigenschaftensammlung für die Anforderung, für die diese Sammlung für die Dauer der Anforderung verfügbar ist.

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

Sie können Pfadinformationen auch von RouteData abrufen. Wenn Speicher mir dient, würde es etwas wie Request.GetRouteData(). Werte; –

+0

@DarrelMiller, ich habe diese Idee verfolgt und mein Gurtzeug scheint nicht so zu funktionieren. var routeData = actionContext.Request.GetRouteData(); var Wert = routeData.Values ​​["MyValue"] als String; Meine routeData enthält nur den Controller-Wert. Lassen Sie mich wissen, wenn Sie nicht zustimmen und ich werde weiter untersuchen. –

+0

Verwenden Sie zuerst einen Autorisierungsfilter, der einen Wert in Anforderungseigenschaften einstellt, und dann ein Aktionsfilter funktioniert. Andere Informationen waren auch nützlich. Danke für Ihre Hilfe. – Ben

1

Eine weitere Alternative zu den Parametern zu erhalten, ist Execute die für die Parameter verbindlich.

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

Hinweis: Sie müssen sicherstellen, dass Sie nur auf den Parametern filtern, die von der Anfrage kommen wird URI, wie ich die Bindung, die Ausführung für alle Parameter bemerkt haben, dass von der Anfrage kommen erwartet Körper wird nicht mehr an die eigentliche Aktion weitergegeben werden. d.h. diese Parameter sind null.

Dies ist nur zu beachten, dass Sie können dies tun, würde ich GetRouteData()/RouteData empfehlen, da es nicht wahrscheinlich ist, den weiteren Fluss von ASP.NET MVC modelbinding zu stören.

var routeData = actionContext.ControllerContext.RouteData; 
var id = routeData.Values["id"] as string; 
Verwandte Themen