首页 > 解决方案 > .net core 2.0 在运行时更改注入的中间件设置

问题描述

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

我在 Asp.net core 2.1 webapi 的配置服务方法中有以下代码

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

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

标签: dependency-injectionasp.net-core-mvcasp.net-core-2.1

解决方案


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

但是,MVC 有授权要求的概念,它在每个请求上执行。这使他们成为您想要实现的目标的绝佳候选人。

在高层次上,我们将:

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

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

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 使用默认授权策略,它只检查用户是否经过身份验证。让我们修改它以在您的类的ConfigureServices方法中添加这个新要求:Startup

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

一切看起来都不错,但我们缺少最后一件。虽然我们将需求添加到策略中,但我们还没有注册需求处理程序,这是 MVC 发现它所必需的。这在该ConfigureServices方法中再次完成。

services.AddScoped<IAuthorizationHandler, ConditionalAnonymousAccessHandler>();

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

请让我知道你的进展如何!


推荐阅读