赖项注入到自定义全局身份验证过滤器和OWIN中间件OAuthAu

赖项注入到自定义全局身份验证过滤器和OWIN中间件OAuthAu

本文介绍了简单的注入器将依赖项注入到自定义全局身份验证过滤器和OWIN中间件OAuthAuthorizationServerProvider中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Simple Injector作为我们的Io​​c容器;我们有两个问题.

I used Simple Injector as our Ioc container; we have two problems.

  1. 我们想注入到我们的自定义身份验证过滤器中;我们阅读了将属性转换为被动属性的文章:转换属性变成被动.但是我们无法将自定义身份验证过滤器属性转换为被动.

  1. We want to inject into our custom authentication filter; we read the post of converting attribute to a passive attribute: Convert Attribute into a passive. But we can't convert custom authentication filter attribute into a passive.

public class BearerAuthentication : Attribute, IAuthenticationFilter
{
   public async Task AuthenticateAsync(
       HttpAuthenticationContext context, CancellationToken cancellationToken)
    {

    }
   public Task ChallengeAsync(
       HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
    {

    }
}

  • 我们想将依赖项注入OWin中间件OAuthAuthorizationServerProvider中;我们知道可以使用开始执行上下文作用域,但是我们需要一个优雅的解决方案.

  • We want to inject dependency into OWin middleware OAuthAuthorizationServerProvider; we know we can use begin execution context scope, but we want an elegant solution.

    using (Ioc.Container.BeginExecutionContextScope())
    {
    
    }
    

  • 已更新

    public interface IAuthenticationFilter<TAttribute> where TAttribute : Attribute
    {
        Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken);
        Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken);
    }
    public  class BearerAuthenticationFilter : Attribute, IAuthenticationFilter<BearerAuthenticationFilter>
    {
        private readonly IAuthenticationBusinessEngine _authenticationBusinessEngine;
        private readonly IHttpContextAccessor _httpContextAccessor;
    
        public BearerAuthenticationFilter(IAuthenticationBusinessEngine authenticationBusinessEngine, IHttpContextAccessor httpContextAccessor)
        {
            _authenticationBusinessEngine = authenticationBusinessEngine;
            _httpContextAccessor = httpContextAccessor;
        }
    
        public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
    
             throw new NotImplementedException();
    
            }
        }
    
        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }
    
    }
    public class AuthenticationFilterDispatcher : IAuthenticationFilter
    {
        private readonly Func<Type, IEnumerable> _container;
        public AuthenticationFilterDispatcher(Func<Type, IEnumerable> container)
        {
            _container = container;
        }
    
        public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            var descriptor = context.ActionContext.ActionDescriptor;
            var attributes = descriptor.ControllerDescriptor.GetCustomAttributes<Attribute>(true)
                .Concat(descriptor.GetCustomAttributes<Attribute>(true));
    
            foreach (var attribute in attributes)
            {
                var filterType = typeof(IAuthenticationFilter<>).MakeGenericType(attribute.GetType());
                var filters = _container.Invoke(filterType);
    
                foreach (dynamic actionFilter in filters)
                {
                    await actionFilter.AuthenticateAsync(context, cancellationToken);
                }
            }
        }
    
        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            throw new NotImplementedException();
        }
    
        public bool AllowMultiple
        {
            get
            {
                return true;
            }
        }
    }
    

    推荐答案

    使用IAuthenticationFilter的等效代码是:

    public interface IAuthenticationFilter<TAttribute> where TAttribute : Attribute
    {
        Task AuthenticateAsync(TAttribute attribute, HttpAuthenticationContext context);
    }
    
    public class AuthenticationFilterDispatcher : IAuthenticationFilter
    {
        private readonly Func<Type, IEnumerable> container;
        public AuthenticationFilterDispatcher(Func<Type, IEnumerable> container) {
            this.container = container;
        }
    
        public async Task AuthenticateAsync(HttpAuthenticationContext context,
            CancellationToken token) {
            var descriptor = context.ActionContext.ActionDescriptor;
            var attributes = descriptor.ControllerDescriptor
                .GetCustomAttributes<Attribute>(true)
                .Concat(descriptor.GetCustomAttributes<Attribute>(true));
    
            foreach (var attribute in attributes) {
                Type filterType = typeof(IAuthenticationFilter<>)
                    .MakeGenericType(attribute.GetType());
                IEnumerable filters = this.container.Invoke(filterType);
    
                foreach (dynamic actionFilter in filters) {
                    await actionFilter.AuthenticateAsync((dynamic)attribute, context);
                }
            }
        }
    
        public async Task ChallengeAsync(HttpAuthenticationChallengeContext context,
            CancellationToken token) { }
    
        public bool AllowMultiple { get { return true; } }
    }
    

    注册过程如下:

    GlobalConfiguration.Configuration.Filters.Add(
        new AuthenticationFilterDispatcher(container.GetAllInstances));
    
    // For Simple Injector 2.x:
    container.RegisterManyForOpenGeneric(typeof(IAuthenticationFilter<>),
        container.RegisterAll,
        new[] { typeof(IAuthenticationFilter<>).Assembly });
    
    // For Simple Injector 3.x:
    container.RegisterCollection(typeof(IAuthenticationFilter<>),
        new[] { typeof(IAuthenticationFilter<>).Assembly });
    

    现在,您可以使属性变为被动状态,并在IAuthenticationFilter<MyPassiveAttribute>实现中实现所需的逻辑,而不是使属性处于活动状态.

    Now instead of making your attributes active, you can make the attribute passive and implement the required logic inside an IAuthenticationFilter<MyPassiveAttribute> implementation.

    您的属性和新组件可能如下所示:

    Your attribute and new component might look like this:

    // NOTE: This attribute does not derive from anything Web API specific,
    // just from Attribute
    public class RequiresBearerAuthenticationAttribute : Attribute
    {
        // put here properties if required
    }
    
    public class BearerAuthenticationFilter
        : IAuthenticationFilter<RequiresBearerAuthenticationAttribute>
    {
        private readonly IAuthenticationBusinessEngine _authenticationBusinessEngine;
        private readonly IHttpContextAccessor _httpContextAccessor;
    
        public BearerAuthenticationFilter(
            IAuthenticationBusinessEngine authenticationBusinessEngine,
            IHttpContextAccessor httpContextAccessor)
        {
            _authenticationBusinessEngine = authenticationBusinessEngine;
            _httpContextAccessor = httpContextAccessor;
        }
    
        public async Task AuthenticateAsync(RequiresBearerAuthenticationAttribute attribute,
            HttpAuthenticationContext context)
        {
            // TODO: Behavior here
        }
    }
    

    这篇关于简单的注入器将依赖项注入到自定义全局身份验证过滤器和OWIN中间件OAuthAuthorizationServerProvider中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-24 00:54