.net Core 2.0在运行时更改注入的中间件设置

时间:2018-10-26 11:56:06

标签: dependency-injection asp.net-core-mvc asp.net-core-2.1

希望我的问题会很清楚。 ;-) 是否可以在运行时更改中间件设置?我会解释更多。

我在Asp.net core 2.1 webapi的configure services方法中有以下代码

services.AddMvc(options =>
                if (!securitySettings)
                {
                  options.Filters.Add(new AllowAnonymousFilter());
                }

我想根据数据库中的设置添加该过滤器。可以在运行时更改它,还是在更改设置后真的需要重新启动应用程序?

1 个答案:

答案 0 :(得分:0)

不幸的是,您无法在应用程序启动后修改应用于MVC的过滤器。

但是,MVC具有authorization requirements的概念,该概念在每个请求上执行。这使它们成为您想要实现的目标的理想之选。

在更高层次上,我们将:

  • 更改默认授权策略以包括自定义要求;
  • 创建可满足此要求的类,即确定是否满足

让我们创建需求类。它是空的,因为它不需要任何参数,因为结果将完全来自数据库:

public class ConditionalAnonymousAccessRequirement : IAuthorizationRequirement
{
}

然后我们创建处理此要求的类:

public class ConditionalAnonymousAccessHandler : AuthorizationHandler<ConditionalAnonymousAccessRequirement>
{
    private readonly AppDbContext _context;

    public ConditionalAnonymousAccessHandler(AppDbContext context)
    {
        _context = context;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ConditionalAnonymousAccessRequirement requirement)
    {
        if (IsAnonymousAccessAllowed())
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }

    private bool IsAnonymousAccessAllowed()
    {
        // Implementation based on the value retrieved from the database
    }
}

实现很简单。如果我们在数据库中发现允许匿名访问,则将此要求标记为成功。如果一项策略中的至少一项要求得到满足,则整个策略成功。


下一步是将该要求添加到授权策略中。默认情况下,当使用不带参数的[Authorize]属性时,MVC使用默认的授权策略just checks that the user is authenticated。让我们对其进行修改,以在您的ConfigureServices类的Startup方法中添加此新要求:

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddRequirements(new ConditionalAnonymousAccessRequirement())
        .Build();
});

一切看起来不错,但我们最后缺了一件。 在将需求添加到策略中时,我们尚未注册需求处理程序is necessary for MVC to discover it。再次通过ConfigureServices方法完成。

services.AddScoped<IAuthorizationHandler, ConditionalAnonymousAccessHandler>();

尽管文档显示处理程序已注册为单例,但在这种情况下,最好按HTTP请求注册处理程序,因为它依赖于DbContext,默认情况下按HTTP请求注册。将处理程序注册为单例意味着DbContext的实例将在整个应用程序生存期内保持活动状态。

请让我知道你的生活!