2012-03-13 8 views
6

Czytałem wiele artykułów, które wskazują, w jaki sposób to zrobić, a mianowicie:wstrzykiwanie atrybutu uwierzytelniania przy użyciu Jedności 2 i MVC 3

Stack overflow solution

Brad Wilsons excellent tutorial

Te wydają się działa dobrze, jednak kiedy śledzę niektóre z wytycznymi stąd

Securing your ASP.NET MVC 3 Application

I wydaje się, że przybył. Problem dotyczy mnie, gdy dodam moją AuthorizationAttribute jako GlobalFilter, a nie tylko dekorację kontrolera/akcji. Chociaż wywołania zależne wydają się być wywoływane i ustawiają moją publiczną właściwość [Dependancy], kiedy faktycznie dochodzi do części kodu, w której zastępuję metodę OnAuthorization() AuthorizeAttribute, mój publiczny atrybut [Dependency] ma wartość null.

Po usunięciu go z filtru globalnego i dekoracji kontrolera wydaje się działać.

Potrafię pisać kod, jeśli potrzeba więcej informacji.

EDIT: do dalszego rozwoju w tej sprawie Oto mój kodu:

Global.asax.cs

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    {       
     // If I have this here the my [Dependency] attribute does not keep it's value 
     // If I remove it and decorate the controller the [Dependency] attribute keeps it value 
     filters.Add(new BasicAuthenticationAttribute()); 
     filters.Add(new HandleErrorAttribute()); 
    } 

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 

     // injection of services and data contexts 
     var container = new UnityContainer(); 

     // injections for services 
     RegisterUnityServices(container); 

     // Filter provides to allow injection into attribute filters 
     RegisterUnityFilters(container); 

    } 

    private void RegisterUnityServices(UnityContainer container) 
    { 
     container.RegisterType<IDataContext, CDAXDataContext>(); 

     container.RegisterType<IUploadService, UploadService>(); 
     container.RegisterType<IAuthenticationService, AuthenticationService>(); 

     // add more services here ...    
     DependencyResolver.SetResolver(new Models.UnityDependencyResolver(container));    
    } 

    private void RegisterUnityFilters(UnityContainer container) 
    { 
     var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider); 
     FilterProviders.Providers.Remove(oldProvider); 

     var provider = new UnityFilterAttributeFilterProvider(container); 
     FilterProviders.Providers.Add(provider);    
    } 

moich klas Unity podjęte od Brada Wilsons Przykłady:

public class UnityDependencyResolver : IDependencyResolver 
{ 
    readonly IUnityContainer _container; 

    public UnityDependencyResolver(IUnityContainer container) 
    { 
     this._container = container; 
    } 

    public object GetService(Type serviceType) 
    { 
     try 
     { 
      return _container.Resolve(serviceType); 
     } 
     catch 
     { 
      return null; 
     } 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     try 
     { 
      return _container.ResolveAll(serviceType); 
     } 
     catch 
     { 
      return new List<object>(); 
     } 
    } 
} 

i

public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider 
{ 
    private IUnityContainer _container; 

    public UnityFilterAttributeFilterProvider(IUnityContainer container) 
    { 
     _container = container; 
    } 

    public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 
    { 
     var filters = base.GetFilters(controllerContext, actionDescriptor); 

     foreach (var filter in filters) 
     { 
      _container.BuildUp(filter.Instance); 
     } 

     return filters; 
    } 

    protected override IEnumerable<FilterAttribute> GetControllerAttributes(
       ControllerContext controllerContext, 
       ActionDescriptor actionDescriptor) 
    { 

     var attributes = base.GetControllerAttributes(controllerContext, 
                 actionDescriptor); 
     foreach (var attribute in attributes) 
     { 
      _container.BuildUp(attribute.GetType(), attribute); 
     } 

     return attributes; 
    } 

    protected override IEnumerable<FilterAttribute> GetActionAttributes(
       ControllerContext controllerContext, 
       ActionDescriptor actionDescriptor) 
    { 

     var attributes = base.GetActionAttributes(controllerContext, 
                actionDescriptor); 
     foreach (var attribute in attributes) 
     { 
      _container.BuildUp(attribute.GetType(), attribute); 
     } 

     return attributes; 
    } 
} 

Podstawy metody My BasicAuthenticationAttribute, w której mam ustawioną właściwość [Dependency], ale nie utrzymuję tej wartości po uruchomieniu metody OnAuthorization.

public class BasicAuthenticationAttribute : AuthorizeAttribute 
{ 
    [Dependency] 
    public IAuthenticationService Authentication { get; set; } 

    private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus) 
    { 
     validationStatus = OnCacheAuthorization(new HttpContextWrapper(context)); 
    } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     // code here that uses the Authentication attribute but it's null 
    } 

Odpowiedz

3

Czy to rozwiązałeś? myślę, że trzeba zadzwonić do DependencyResolver w klasie atrybutu ... Nie wiem, czy atrybut [Dependency] pracuje tutaj ... tak w wezwaniu OnAuthorization metoda IAuthenticationService authentication = DependencyResolver.Current.GetService<IAuthenticationService>();

+0

nie zrobiłem. To dziwne, że działa, gdy dekoruję kontroler, ale nie działa, jeśli umieściłem go w pliku global.ascx. Podam twoją metodę, ale naprawdę chciałem ją zaimplementować poprzez DIP używając Unity. W tej chwili działa, ale metoda wyjaśniona w tym, że dekoruję kontroler i nie włączam go do pliku globalnego. – dreza

+0

Znalazłem to samo zachowanie, działało dobrze w kontrolerze, ale nie w atrybucie/filtrze ... po prostu go tam nie było, więc musiałem zadzwonić do DependencyResolver. Bardzo ciekawy komentarz od http://stackoverflow.com/users/759701/ethan-cabiac "nie chodzi o to, czy są one zarejestrowane, chodzi o to, w jaki sposób są tworzone." Zasadniczo, framework nazywa nowy Authenticate(), który omija każdą DI-Container "w tym pytaniu http://stackoverflow.com/questions/6121050/mvc-3-unity-2-inject-dependencies-into-a-filter – w4ik

Powiązane problemy