正在检查ASP.NET核心标识中具有Authorize属性的多个策略之一



我在ASP.NET Core应用程序中设置了一个标准身份验证系统。

用户、角色、角色声明(充当权限)

在Startup.cs中,我为每个角色和每个权限创建了一个策略。假设这将使我在视图中具有充分的灵活性,可以说我希望此按钮显示用户是否是具有DeleteCustomer声明的角色的一部分,或者用户是否属于角色Superuser。

如何使用Authorize属性执行OR条件。例如,在我的整个网站上,我希望SuperuserRole Policy对所有内容都拥有完全权限。

在一个操作方法上,让我们假设我有以下内容:

[授权(策略="编辑客户")]

这需要将登录用户分配给具有声明的角色:Edit.Customer,因为我正在为声明Edit.Customer.创建策略。这一切都很好,但我如何说我希望任何具有角色超级用户的用户都能够访问EditCustomer操作方法。超级用户作为角色在数据库中,并作为名为RequireSuperUser的策略添加。

您可以在Startup.cs:中添加OR条件

services.AddAuthorization(options => {
options.AddPolicy("EditCustomer", policy =>
policy.RequireAssertion(context => 
context.User.HasClaim(c => (c.Type == "DeleteCustomer" || c.Type == "Superuser"))));
});

我也面临着类似的问题,我只想让"John Doe"、"Jane Doe"用户查看"Ending Contracts"屏幕,或者只希望"MIS"部门的任何人也能访问同一屏幕。以下对我有效,我有索赔类型"部门"one_answers"用户名":

services.AddAuthorization(options => {
options.AddPolicy("EndingContracts", policy =>
policy.RequireAssertion(context => context.User.HasClaim(c => (c.Type == "department" && c.Value == "MIS" ||
c.Type == "UserName" && "John Doe, Jane Doe".Contains(c.Value)))));
});

您可以使用两个不同的AuthorizationHandler处理程序来满足IAuthorizationRequirement:的相同要求

public class FooOrBooRequirement : IAuthorizationRequirement { }
public class FooHandler : AuthorizationHandler<FooOrBooRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationContext context, FooOrBooRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "Foo" && c.Value == true))
{
context.Succeed(requirement);
return Task.FromResult(0);
}
}
}
public class BooHandler : AuthorizationHandler<FooOrBooRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationContext context, FooOrBooRequirement requirement)
{
if (context.User.HasClaim(c => c.Type == "Boo" && c.Value == true))
{
context.Succeed(requirement);
return Task.FromResult(0);
}
}
}

因此,在AddPolicy中,FooHandlerBooHandler:只能满足一个要求

services.AddAuthorization(authorizationOptions =>
{
authorizationOptions.AddPolicy(
"MustBeFooOrBoo",
policyBuilder =>
{
policyBuilder.RequireAuthenticatedUser();
policyBuilder.AddRequirements(new FooOrBooRequirement());
});
});

请注意,AuthorizationHandler提供了一个更强大的自定义策略,因此它只与需要更复杂身份验证的特殊情况最相关,例如,如果您想确定用户是否是资源所有者。

对于一个简单的基于索赔的政策,我建议使用@richardmneyan的答案。

我们可以向AuthorizationHandler注入DBContext(如果使用EF,或者如果不使用用户存储库)或HttpContextAccessor来实现这一点。

通过注入EF上下文(或用户存储库),我们可以查询数据库以确定当前用户是否是超级用户。

或者通过注入HttpContextAccessor,我们可以从中确定用户是否是超级用户。这种方法比第一种方法更快,但取决于用户上下文是否具有所需的信息。

为了实现这一点,假设您拥有EditCustomerRequirementEditCustomerAuthorizationHandler:

public class EditCustomerAuthorizationHandler: AuthorizationHandler<EditCustomerRequirement>
{
readonly AppDbContext _context;
readonly IHttpContextAccessor _contextAccessor;
public EditCustomerAuthorizationHandler(DbContext c, IHttpContextAccessor ca)
{
_context = c;
_contextAccessor = ca;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, EditCustomerRequirement requirement)
{
//here we have the access to DB and HttpContext
//we can get the information if the user is superuser from either db or httpContext 
var isSuperUser = await IsSuperUser(_context);
//or
var isSuperUser = IsSuperUser(_contextAccessor);
if(isSuperUser) 
{
context.Succeed(requirement);
}
else
{
//the current implementation of EditCustomer Policy
}
}
}

IsSuperUser是我们可以从db上下文或http上下文中获取信息的某种方法。

相关内容

  • 没有找到相关文章

最新更新