Да, вы можете!
Система авторизации в ASP. NET Ядро расширяемо, и вы можете легко реализовать свой сценарий с авторизацией на основе poliy .
Для начала необходимо знать две основные вещи:
- политика авторизации состоит из одного или нескольких требований
- все требования должны быть выполнены для политика для достижения успеха
Наша цель состоит в том, чтобы затем создать требование, которое удовлетворяется, если выполняется любое из следующих утверждений:
- режим обслуживания не включен или
- пользователь аутентифицирован
Давайте посмотрим код!
Первый шаг - создать наше требование:
public class MaintenanceModeDisabledOrAuthenticatedUserRequirement : IAuthorizationRequirement
{
}
Затем мы должен реализовать обработчик для этого требования, который будет определять, удовлетворен ли он или нет. Хорошая новость заключается в том, что обработчики поддерживают внедрение зависимостей:
public class MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler : AuthorizationHandler<MaintenanceModeDisabledOrAuthenticatedUserRequirement>
{
private readonly IMaintenanceModeDataService _maintenanceModeService;
public MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler(IMaintenanceModeDataService maintenanceModeService)
{
_maintenanceModeService = maintenanceModeService;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MaintenanceModeDisabledOrAuthenticatedUserRequirement requirement)
{
if (!_maintenanceModeService.IsMaintenanceModeEnabled || context.User.Identities.Any(x => x.IsAuthenticated))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
Далее нам нужно создать политику авторизации, которая использует это требование, и у вас есть 2 варианта:
- , которые вы можете переопределить политику по умолчанию, используемую при использовании «пустых» атрибутов
[Authorize]
, или - создать явную политику, на которую вам придется ссылаться в ваших атрибутах, например
[Authorize(Policy = "<your-policy-name>")]
Там нет правильного или неправильного ответа; Я бы выбрал первый вариант, если у моего приложения была только одна политика авторизации, и второй, если у него было несколько из них. Мы увидим, как это сделать:
services
.AddAuthorization(options =>
{
// 1. This is how you redefine the default policy
// By default, it requires the user to be authenticated
//
// See https://github.com/dotnet/aspnetcore/blob/30eec7d2ae99ad86cfd9fca8759bac0214de7b12/src/Security/Authorization/Core/src/AuthorizationOptions.cs#L22-L28
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.AddRequirements(new MaintenanceModeDisabledOrAuthenticatedUserRequirement())
.Build();
// 2. Define a specific, named policy that you can reference from your [Authorize] attributes
options.AddPolicy("MaintenanceModeDisabledOrAuthenticatedUser", builder => builder
.AddRequirements(new MaintenanceModeDisabledOrAuthenticatedUserRequirement()));
});
Далее вам необходимо зарегистрировать обработчик требований как IAuthorizationHandler
, как указано в официальных документах
// The lifetime you pick is up to you
// You just need to remember that it's got a dependency on IMaintenanceModeDataService, so if you
// registered the implementation of IMaintenanceModeDataService as a scoped service, you shouldn't
// register the handler as a singleton
// See this captive dependency article from Mark Seeman: https://blog.ploeh.dk/2014/06/02/captive-dependency/
services.AddScoped<IAuthorizationHandler, MaintenanceModeDisabledOrAuthenticatedUserRequirementHandler>();
Последний шаг - применение атрибутов [Authorize]
к контроллерам / действиям по мере необходимости.
// 1. If you redefined the default policy
[Authorize]
public IActionResult Index()
{
return View();
}
// 2. If you defined an explicit policy
[Authorize(Policy = "MaintenanceModeDisabledOrAuthenticatedUser")]
public IActionResult Index()
{
return View();
}