2013-05-23 12 views
12

Mam kilka prostych tras, które chcę ograniczyć za pomocą prostego parametru zapytania. Jeśli klucz jest niepoprawny lub nie został podany, chciałbym rzucić NotAuthorizedException.Czy powinienem używać IAuthorizationFilter, jeśli chcę utworzyć ograniczony zasób ApiKey z ASP.NET MVC4?

Proszę nie sugerować korzystania z WebApi lub equiv - nie mogę jeszcze w tym scenariuszu.

Więc nie jestem pewien, czy powinienem wdrożyć IAuthorizationFilter lub wykonać IActionFilter lub nawet coś innego.

Moja logika kodu?

  • Sprawdź kursor dla klucza.
  • Sprawdź mój RavenDb (repozytorium) dla użytkownika z tym kluczem/wartością.

Jeśli nie przejdą one żadnej z tych kontroli, należy wyrzucić NotAuthorizedException.

Zakładam, że wtedy ozdobiłbym moją metodę działania tym filtrem. Zakładam również, że będę musiał przekazać w moim repozytorium również tę metodę działania?

Wszelkie sugestie proszę?

Odpowiedz

25

więc nie jestem pewien, czy powinien być wdrożenie IAuthorizationFilter lub wdrożenie IActionFilter lub nawet coś innego.

Powinieneś być wdrożenie IAuthorizationFilter:

public class MyAuthorizeAttribute: FilterAttribute, IAuthorizationFilter 
{ 
    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var key = filterContext.HttpContext.Request.QueryString["param_name"]; 
     if (!IsValid(key)) 
     { 
      // Unauthorized! 
      filterContext.Result = new HttpUnauthorizedResult(); 
     } 
    } 

    private bool IsValid(string key) 
    { 
     // You know what to do here => go hit your RavenDb 
     // and perform the necessary checks 
     throw new NotImplementedException(); 
    } 
} 

A jeśli chciał użyć iniekcji zależność w filtrze akcji niestandardowej można spojrzeć na following article w którym można zaimplementować dostawcę filtr niestandardowy (IFilterProvider). Możesz mieć zaznaczony atrybut, który możesz wykorzystać w działaniach kontrolera, a następnie poprosić tego niestandardowego dostawcę filtru, aby po prostu sprawdził, czy akcja została ozdobiona tym atrybutem znacznika i zastosuje niestandardowy filtr autoryzacji.

Na przykład:

public class MyAuthorizeAttribute: Attribute 
{ 

} 

a filtr autoryzacja będzie tylko wdrożyć IAuthorizationFilter, nie będzie FilterAttribute:

public class MyAuthorizationFilter: IAuthorizationFilter 
{ 
    private readonly ISomeRepository repository; 
    public class MyAuthorizationFilter(ISomeRepository repository) 
    { 
     this.repository = repository; 
    } 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     var key = filterContext.HttpContext.Request.QueryString["param_name"]; 
     if (!IsValid(key)) 
     { 
      // Unauthorized! 
      filterContext.Result = new HttpUnauthorizedResult(); 
     } 
    } 

    private bool IsValid(string key) 
    { 
     // You know what to do here => go hit your RavenDb 
     // and perform the necessary checks 
     throw new NotImplementedException(); 
    } 
} 

a następnie trzeba będzie dostawcy niestandardowy filtr:

public class MyFilterProvider : IFilterProvider 
{ 
    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
    { 
     if (actionDescriptor.GetCustomAttributes(typeof(MyAuthorizeAttribute), true).Any()) 
     { 
      var filter = DependencyResolver.Current.GetService<MyAuthorizationFilter>(); 
      yield return new Filter(filter, FilterScope.Global); 
     } 

     yield break; 
    } 
} 

które zostanie zarejestrowane w tobie r Application_Start:

FilterProviders.Providers.Add(new MyFilterProvider()); 
+0

Dzięki hałdom Darin! Zauważyłem, że użyłeś Property Injection (myślę, że tak to się nazywa) zamiast Constructor Injection - czy jest jakikolwiek powód, dla którego nie mógłbym tego zrobić w klasie 'MyAuthorizationFilter' .. i niech również' MyAuthorizationFilter' dziedziczy po 'Property Injection '. FilterAttribute'? Wtedy miałbym tylko 1 klasę, a nie 2. –

+0

Nie, używa on wtrysku konstruktora. To właśnie robi 'DependencyResolver' w' MyFilterProvider'.Zakładam, że nie możesz użyć pojedynczej klasy, ponieważ struktura nie tworzy atrybutów za pomocą DependencyResolver i jako taka, nie możesz udekorować swoich działań, ponieważ potrzebuje 'Repozytorium 'przekazanego do konstruktora i ciebie nie będzie dostępna. Czy istnieje lepszy sposób wykonywania iniekcji konstruktora na atrybutach, ponieważ implementacja ta utrudni wykonywanie takich rzeczy jak '[MyAuthorize (ErrorMessage =" Sad panda ")]'. – ajbeaven

+0

@ajbeaven Możesz dokonać atrybutu z parametrami tak, jak byś chciał, a następnie ustawić je jako właściwości wewnętrzne i uzyskać atrybut z poziomu filtru autoryzacyjnego, aby uzyskać dostęp do jego właściwości/pól. Użyj "filterContext.ActionDescriptor.GetCustomAttributes (typeof (YourClass), true) .Cast ();", aby uzyskać atrybut. Zakres wewnętrzny jest przydatny, jeśli masz dedykowany projekt dla nich; inaczej, po prostu róbcie ściągacze. –

Powiązane problemy