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());
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. –
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
@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. –