Ich habe eine Situation, in der ich einige Abhängigkeiten in einem Aktionsfilter einspeisen muss, nämlich meinen benutzerdefinierten Autorisierungsanbieter in meinem benutzerdefinierten Autorisierungsattribut. Ich stolperte über viele Leute und Beiträge, die sagten, dass wir die "Attribut-Metadaten" vom "Verhalten" trennen sollten. Dies ist sinnvoll und es gibt auch die Tatsache, dass Filterattribute nicht durch den 'DependencyResolver' instanziiert werden, so dass es schwierig ist, die Abhängigkeiten zu injizieren.IFilterProvider und Trennung von Bedenken
Also habe ich ein wenig Refactoring meines Codes gemacht und ich wollte wissen, ob ich es richtig gemacht habe (ich benutze Castle Windsor als das DI-Framework).
Zunächst einmal zog ich mein Attribut nur die Rohdaten enthalten Ich brauche
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthorizeAttribute : Attribute
{
public string Code { get; set; }
}
ich eine benutzerdefinierte Berechtigungs Filter erzeugt, der die Logik der Bestimmung, ob der aktuelle Benutzer über die Berechtigung
public class MyAuthorizationFilter : IAuthorizationFilter
{
private IAuthorizationProvider _authorizationProvider;
private string _code;
public MyAuthorizationFilter(IAuthorizationProvider authorizationProvider, string code)
{
Contract.Requires(authorizationProvider != null);
Contract.Requires(!string.IsNullOrWhiteSpace(code));
_authorizationProvider = authorizationProvider;
_code = code;
}
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.HttpContext.Request.IsAuthenticated)
{
BaseController controller = filterContext.Controller as BaseController;
if (controller != null)
{
if (!IsAuthorized(controller.CurrentUser, controller.GetCurrentSecurityContext()))
{
// forbidden
filterContext.RequestContext.HttpContext.Response.StatusCode = 403;
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.Result = new RedirectToRouteResult("default", new RouteValueDictionary(new
{
action = "http403",
controller = "error"
}), false);
}
else
{
filterContext.Result = controller.InvokeHttp404(filterContext.HttpContext);
}
}
}
else
{
}
}
else
{
filterContext.Result = new RedirectResult(FormsAuthentication.LoginUrl);
}
}
private bool IsAuthorized(MyUser user, BaseSecurityContext securityContext)
{
bool has = false;
if (_authorizationProvider != null && !string.IsNullOrWhiteSpace(_code))
{
if (user != null)
{
if (securityContext != null)
{
has = _authorizationProvider.HasPermission(user, _code, securityContext);
}
}
}
else
{
has = true;
}
return has;
}
}
enthalten würde
Der letzte Teil bestand darin, einen benutzerdefinierten Filteranbieter zu erstellen, der dieses spezifische Attribut abrufen und meinen benutzerdefinierten Filter instanziieren würde, indem er seine Abhängigkeiten und alle Daten, die er benötigt, aus dem Attribut extrahierte.
public class MyAuthorizationFilterProvider : IFilterProvider
{
private IWindsorContainer _container;
public MyAuthorizationFilterProvider(IWindsorContainer container)
{
Contract.Requires(container != null);
_container = container;
}
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
Type controllerType = controllerContext.Controller.GetType();
var authorizationProvider = _container.Resolve<IAuthorizationProvider>();
foreach (MyAuthorizeAttribute attribute in controllerType.GetCustomAttributes(typeof(MyAuthorizeAttribute), false))
{
yield return new Filter(new MyAuthorizationFilter(authorizationProvider, attribute.Code), FilterScope.Controller, 0);
}
foreach (MyAuthorizeAttribute attribute in actionDescriptor.GetCustomAttributes(typeof(MyAuthorizeAttribute), false))
{
yield return new Filter(new MyAuthorizationFilter(authorizationProvider, attribute.Code), FilterScope.Action, 0);
}
}
}
Der letzte Schritt ist der der Filteranbieter im
global.asax registrierenFilterProviders.Providers.Add(new MyAuthorizationFilterProvider(_container));
Also zuerst frage ich mich, wenn ich auf die Idee richtig und zweite bekam, was verbessert werden könnte.
Hallo Francois, ich kam mit einer ziemlich ähnlichen Lösung für das gleiche Problem wie Sie. Ich stelle mir gerade die gleichen Fragen wie Sie. Haben Sie am Ende diese Lösung verwendet? Irgendein Problem damit im Laufe der Zeit? Hast du eine Empfehlung? Vielen Dank. –