我已在ASP.NET Core应用程序中设置了标准身份验证系统。
用户,角色,RoleClaims(充当权限)
在Startup.cs中,我为每个角色和每个权限创建一个策略。假设这会让我在视图中具有完全的灵活性,可以说我希望此按钮显示用户是否是声明DeleteCustomer的角色的一部分,或者用户是否属于角色超级用户。
如何使用Authorize属性执行OR条件。例如,在我的整个网站中,我希望SuperuserRole Policy拥有对所有内容的完全权限。
通过动作方法,我想说我有以下内容:
[授权(Policy =“EditCustomer”)]
这将要求已登录的用户被分配到具有声明的角色:Edit.Customer,因为我正在为声明Edit.Customer创建策略。这一切都运行正常,但我怎么说我希望任何具有角色超级用户的用户能够访问EditCustomer操作方法。超级用户作为角色位于数据库中,另外还添加为名为RequireSuperUser的策略。
答案 0 :(得分:6)
您可以在Startup.cs中添加OR条件:
services.AddAuthorization(options => {
options.AddPolicy("EditCustomer", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c => (c.Type == "DeleteCustomer" || c.Type == "Superuser"))));
});
我面临着类似的问题,我只想和#34; John Doe"," Jane Doe"用户查看"结束合同"屏幕或任何人只能来自" MIS"部门也能够访问同一个屏幕。以下是我的工作,我索赔类型"部门"和"用户名":
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)))));
});
答案 1 :(得分:0)
您可以使用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
中,您只有FooHandler
或BooHandler
可以满足的一项要求:
services.AddAuthorization(authorizationOptions =>
{
authorizationOptions.AddPolicy(
"MustBeFooOrBoo",
policyBuilder =>
{
policyBuilder.RequireAuthenticatedUser();
policyBuilder.AddRequirements(new FooOrBooRequirement());
});
});
请注意,AuthorizationHandler
提供了更强大的自定义策略,因此它仅与需要更复杂身份验证的特殊情况(例如,如果您要确定用户是否为资源所有者)最相关。
对于仅基于索赔的简单政策,我建议使用@ richard-mneyan的答案。
答案 2 :(得分:0)
我们可以向AuthorizationHandler
注入DBContext(如果使用EF或不使用用户存储库)或HttpContextAccessor来实现这一目标。
通过注入EF上下文(或用户存储库),我们可以查询数据库以确定当前用户是否是超级用户。
或者通过注入HttpContextAccessor
,我们可以从中确定用户是否是超级用户。这种方法比第一种更快,但是取决于用户上下文是否具有所需的信息。
要实现此目标,请假设您拥有EditCustomerRequirement
和EditCustomerAuthorizationHandler
:
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
是我们可以用来从数据库上下文或http上下文中获取信息的某种方法。