如何在ASP.NET Core中使用IAsyncAuthorizationFilter获取依赖项注入

Mat*_*tze 2 c# autofac .net-core asp.net-core

我已经实现了IAsyncAuthorizationFilter一个类的接口;此外,该类是从派生的Attribute,因此我可以使用它来标记控制器类和操作方法。到目前为止,该方法有效;该Task OnAuthorizationAsync(AuthorizationFilterContext context)方法在action方法之前被调用,如果请求未通过身份验证,HTTP 401则为响应返回。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class CustomAuthenticationAttribute : Attribute, IAsyncAuthorizationFilter 
{
    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

该属性的用法如下...

[CustomAuthenticationAttribute]
public class SomeDataController : Controller
{
    [HttpGet]
    public async Task GetData()
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我想使用应用程序服务(该服务从数据库中获取身份验证所需的秘密私钥信息),并尝试为此使用属性注入。通过ctor注入依赖不是一个好的选择,因为它是作为属性实现的。所以我尝试了...

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class CustomAuthenticationAttribute : Attribute, IAsyncAuthorizationFilter 
{
    public IPrivateKeyLookupService KeyService { get; set; }

    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        string publicKey = ...
        ...
        var privateKey = await this.KeyService.GetPrivateKeyFrom(publicKey);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

...但是财产注入似乎在这里不起作用。该服务已在IoC中注册,但属性未连接。这是我使用的ASP.NET Core 1.1项目Autofac。在Startup类中,我的ConfigureServices方法有类似的东西...

public void ConfigureServices(IServicesCollection collection)
{
    ...

    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterType<AuthKeyService>().As<IPrivateKeyLookupService>();

    containerBuilder.Populate(services);

    this.container = containerBuilder.Build();
}
Run Code Online (Sandbox Code Playgroud)

是否Autofac支持自动接线IAsyncAuthorizationFilter类型?如果没有,我该如何填充该功能?

Mat*_*tze 6

事实证明非常简单...

ASP.NET Core其中,该TypeFilter属性也是一个过滤器,它创建另一个过滤器(由指定Type),并通过涉及依赖项注入来满足其构造函数参数。

我改变了执行IAsyncAuthorizationFilter; 删除了属性并添加了一个ctor,因为使用TypeFilterctor注入现在可以工作了...

public sealed class CustomAuthenticationAttribute : IAsyncAuthorizationFilter 
{
    private readonly IPrivateKeyLookupService keyService;
    public CustomAuthenticationAttribute(
        IPrivateKeyLookupService keyService)
    {
        this.keyService = keyService;
    }

    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我还从中删除了继承,Attribute因为不再需要继承以及AttributeUsage属性的声明。

因此,我可以如下使用我的属性...

[TypeFilter(typeof(CustomAuthenticationAttribute))]
public class SomeDataController : Controller
{
    [HttpGet]
    public async Task GetData()
    {
        ...
    }
} 
Run Code Online (Sandbox Code Playgroud)

也可以通过类的object[] Arguments属性将其他参数传递给过滤器的ctor TypeFilter