是的你可以!
ASP.NET Core 中的授权系统是可扩展的,您可以使用以下命令轻松实现您的场景基于策略的授权 https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2.
开始之前需要了解两件主要事情:
- 授权策略由一个或多个组成要求 https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2#requirements-1
- 政策要想成功就必须满足所有要求
我们的目标是创建一个要求,如果以下任何陈述为真,则满足该要求:
我们来看看代码吧!
第一步是创建我们的需求:
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
,如所示官方文档 https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2#handler-registration-1
// 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();
}