自定义AuthenticationHandler不使用自定义服务提供程序进行依赖项注入

时间:2017-09-28 13:30:58

标签: asp.net-mvc asp.net-core-mvc

我添加了这样的自定义授权方案......

public class AuthHandler : AuthenticationHandler<AuthOptions>
{
    private readonly IUserIdentifierProvider userIdentifierProvider;

    public AuthHandler(IUserIdentifierProvider userIdentifierProvider, IOptionsMonitor<AuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) :
        base(options, logger, encoder, clock)
    {
        this.userIdentifierProvider = userIdentifierProvider;
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()    {
        var ticket = ...

        return Task.FromResult(AuthenticateResult.Success(ticket));
    }
}
    public static class AuthMiddlewareAppBuilderExtensions
    {
        public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<AuthOptions> configureOptions)
        {
            return builder.AddScheme<AuthOptions, AuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
        }
    }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddMemoryCache();

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = "Custom Scheme";
                options.DefaultChallengeScheme = "Custom Auth";
            })
            .AddCustomAuth(o => {});

            services.AddDbContext<DomainDbContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            });

            var serviceProvider = ConfigureUnity(services);

            return serviceProvider;
        }

当MVC根据请求创建AuthHandler类时,它不使用从ConfigureServices返回的依赖注入容器。

我得到例外......

  

InvalidOperationException:无法解析类型的服务   尝试时'Web.Auth.Abs​​tract.IUserIdentifierProvider'   激活'AuthHandler'。

为什么不使用我的容器?

如果我这样做的话......

services.AddTransient<IUserIdentifierProvider, UserIdentifierProvider>();

在ConfigureServices中。它似乎根本没有在我的容器中查找。那么它到底是从哪个地方获取实例的呢?它必须保持对传递给ConfigureServices的IServiceCollection的引用,并使用它而不是它应该的那个。

使用Reflector查看,ConfigureServices方法由以下函数调用...

public static StartupMethods LoadMethods(IServiceProvider hostingServiceProvider, Type startupType, string environmentName)
{
    ConfigureBuilder builder = FindConfigureDelegate(startupType, environmentName);
    ConfigureServicesBuilder builder2 = FindConfigureServicesDelegate(startupType, environmentName);
    ConfigureContainerBuilder configureContainerMethod = FindConfigureContainerDelegate(startupType, environmentName);
    object instance = null;
    if (!builder.MethodInfo.get_IsStatic() || ((builder2 != null) && !builder2.MethodInfo.get_IsStatic()))
    {
        instance = ActivatorUtilities.GetServiceOrCreateInstance(hostingServiceProvider, startupType);
    }
    Func<IServiceCollection, IServiceProvider> configureServicesCallback = builder2.Build(instance);
    Action<object> configureContainerCallback = configureContainerMethod.Build(instance);
    return new StartupMethods(instance, builder.Build(instance), delegate (IServiceCollection services) {
        IServiceProvider provider = configureServicesCallback(services);
        if (provider != null)
        {
            return provider;
        }
        if (configureContainerMethod.MethodInfo != null)
        {
            Type[] typeArray1 = new Type[] { configureContainerMethod.GetContainerType() };
            Type serviceType = typeof(IServiceProviderFactory<>).MakeGenericType(typeArray1);
            object requiredService = hostingServiceProvider.GetRequiredService(serviceType);
            object[] objArray1 = new object[] { services };
            object obj3 = serviceType.GetMethod("CreateBuilder").Invoke(requiredService, objArray1);
            configureContainerCallback(obj3);
            object[] objArray2 = new object[] { obj3 };
            provider = (IServiceProvider) serviceType.GetMethod("CreateServiceProvider").Invoke(requiredService, objArray2);
        }
        else
        {
            provider = hostingServiceProvider.GetRequiredService<IServiceProviderFactory<IServiceCollection>>().CreateServiceProvider(services);
        }
        return provider ?? services.BuildServiceProvider();
    });
}

如果退回提供者,则已完成。

这没有任何意义。

1 个答案:

答案 0 :(得分:0)

我在auth处理程序构造函数中对依赖项进行了硬编码。

简单,嗯?