К сожалению, вы не можете изменить фильтры, примененные к 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-запроса. Регистрация обработчика в качестве одиночного означает, что экземпляр DbContext будет поддерживаться в течение всего времени жизни приложения.
Пожалуйста, дайте мне знать, как вы идете!