如何将应用程序服务注入AuthenticationHandler

时间:2018-12-25 12:30:10

标签: c# asp.net-core simple-injector

我有一个依赖于应用程序服务的自定义AuthenticationHandler<>实现。有没有一种方法可以解决Simple Injector对AuthenticationHandler的依赖性?还是跨线注册,以便可以从IServiceCollection解析应用程序服务?

为简单起见,示例实现如下所示:

public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    private readonly ITokenDecryptor tokenDecryptor;

    public SecurityTokenAuthHandler(ITokenDecryptor tokenDecryptor,
        IOptionsMonitor<AuthenticationSchemeOptions> options, 
        ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) :
        base(options, logger, encoder, clock) =>
        this.tokenDecryptor = tokenDecryptor;

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync() =>
        return tokenDecryptor.Decrypt(this);
}

...

services.AddAuthentication("Scheme")
    .AddScheme<AuthenticationSchemeOptions, AuthHandler>("Scheme", options => { });

当前的解决方案是手动跨线应用程序服务,这不太方便:

services.AddTransient(provider => container.GetInstance<ITokenDecryptor>());

2 个答案:

答案 0 :(得分:3)

  

也许是跨线注册,以便可以使用应用程序服务   从IServiceCollection解决?

否,.Net Core无法自动从Simple Injector解析服务。

  

交叉布线是一种单向过程。通过使用   AutoCrossWireAspNetComponents,ASP.NET的配置系统不会   自动从Simple Injector中解决其缺少的依赖关系。   当由Simple Injector组成的应用程序组件需要   被注入到框架或第三方组件中,这必须是   通过将ServiceDescriptor添加到   IServiceCollection,它向Simple Injector请求依赖项。   但是,这种做法应该很少见。

参考:Cross-wiring ASP.NET and third-party services

作为上面的建议,您需要在IServiceCollection中注册服务。您当前已实现的。

答案 1 :(得分:1)

陶的答案是正确的。实现此目的最简单的方法是将AuthHandler交叉布线到Simple Injector。

这可以如下进行:

// Your original configuration:
services.AddAuthentication("Scheme")
    .AddScheme<AuthenticationSchemeOptions, AuthHandler>("Scheme", options => { });

// Cross-wire AuthHandler; let Simple Injector create AuthHandler.
// Note: this must be done after the call to AddScheme. Otherwise this registration
// won't be picked up by ASP.NET.
services.AddTransient(c => container.GetInstance<AuthHandler>());

// Register the handler with its dependencies (in your case ITokenDecryptor) with 
// Simple Injector
container.Register<AuthHandler>();
container.Register<ITokenDecryptor, MyAwesomeTokenDecryptor>(Lifestyle.Singleton);