我刚开始使用ASP.NET核心标识并定义了以下要求:
public sealed class IsCustomerUserRequirement : IAuthorizationRequirement
public sealed class IsSuperUserRequirement : IAuthorizationRequirement
使用以下基本处理程序:
public class IsCustomerUserHandler : AuthorizationHandler<IsCustomerUserRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsCustomerUserRequirement requirement)
{
if (context.User.HasClaim(_ => _.Type == "customer"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class IsSuperUserHandler : AuthorizationHandler<IsSuperUserRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IsSuperUserRequirement requirement)
{
if (context.User.IsInRole("super_user"))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
然后我可以把它们放在基本政策中:
services
.AddAuthorization(options =>
{
options.AddPolicy("MustBeSuperUser", policy => policy.Requirements.Add(new IsSuperUserRequirement()));
options.AddPolicy("CustomersOnly", policy => policy.Requirements.Add(new IsCustomerUserRequirement()));
});
使用[Authorize("CustomersOnly")]
应用它,效果很好。
我的要求 是允许超级用户,声明具有super_user
角色的主体但没有 {{ 1}}声明,也可以访问仅限客户的区域。
我目前通过将处理程序更改为手动检查来实现此目的:
customer
我的问题 这就像我错过了这一点。有没有更好的方法来定义这个,所以我不必在将来重复每个处理程序中的超级用户检查?
<小时/> 所有这一切的大局是我使用IdentityServer4(ASP.NET身份支持)进行身份验证,然后打算使用一些基于JWT的声明(一个声明,两个角色)来进一步识别用户授权属于特定于应用程序角色/权限结构和一些与Identity Server无关的自定义中间件。围绕这个主题有什么最佳实践?
答案 0 :(得分:3)
“感觉就像我错过了这一点” - 是的,在某种程度上你忽略了这一点。您正在进行基于角色的授权:用户可以是客户或超级用户。
但相反,新模型是基于声明的授权,其中用户对某些内容有所声明,并且您正在使用它来授权它们。理想情况下,超级用户会得到客户获得的相同声明,并允许以这种方式访问资源。这样的声明当时也不会被称为customer
,而是用户的属性。
您仍然可以使用基于角色的授权模型和声明,但您应该避免混合它们。正如你自己注意到的那样,这最终会变得有些奇怪。
话虽如此,有多种方法可以使用不同的要求来成功实施政策。如果您仅使用角色(而不是customer
声明),则可以使用内置方式:
options.AddPolicy("MustBeSuperUser", policy => policy.RequireRole("super_user"));
options.AddPolicy("CustomersOnly", policy => policy.RequireRole("customer", "super_user"));
这样,CustomersOnly
和customer
角色都会实现super_user
政策。
由于您没有为客户使用角色,因此您必须在此处遵循您的要求实施。授权要求的工作方式是,您可以为同一需求类型提供多个处理程序,并且只有其中一个需要成功(只要没有失败)才能成功。
因此,您可以让IsSuperUserHandler
处理多项要求。你可以按照AuthorizationHandler<T>
的实施来完成这项工作:
public class IsSuperUserHandler : IAuthorizationHandler
{
public virtual async Task HandleAsync(AuthorizationHandlerContext context)
{
foreach (var req in context.Requirements)
{
if (req is IsSuperUserRequirement || req is IsCustomerUserRequirement)
{
if (context.User.IsInRole("super_user"))
context.Succeed(req);
}
}
}
}
因此,IsSuperUserHandler
现在是IsSuperUserRequirement
和IsCustomerUserRequirement
的授权处理程序。因此,超级用户也将履行需要CustomersOnly
的{{1}}政策。