简单注入器将依赖项注入自定义全局身份验证过滤器和 OWIN 中间件 OAuthAuthorizationServerProvider
Simple Injector inject dependency into custom global authentication filters and OWIN middle ware OAuthAuthorizationServerProvider
我使用 Simple Injector 作为我们的 Ioc 容器;我们有两个问题。
我们要注入我们的自定义身份验证过滤器;我们阅读了 post 将属性转换为被动属性:Convert 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中注入依赖;我们知道我们可以使用开始执行上下文范围,但我们想要一个优雅的解决方案。
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>
实现中实现所需的逻辑,而不是让属性变为主动。
您的属性和新组件可能如下所示:
// 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
}
}
我使用 Simple Injector 作为我们的 Ioc 容器;我们有两个问题。
我们要注入我们的自定义身份验证过滤器;我们阅读了 post 将属性转换为被动属性:Convert 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中注入依赖;我们知道我们可以使用开始执行上下文范围,但我们想要一个优雅的解决方案。
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>
实现中实现所需的逻辑,而不是让属性变为主动。
您的属性和新组件可能如下所示:
// 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
}
}