ASP.NET 标识中角色与声明的最佳实践

我是完全新的使用 claimsASP.NETIdentity,并希望得到一个最佳做法在使用 Roles and/or Claims的想法。

读了这么多,我还是有问题。

问: 我们不再使用角色了吗?
问: 如果是这样,为什么角色仍然提供?
问: 我们应该只使用索赔吗?
Q: Should we use Roles & Claims together?

我最初的想法是我们“应该”一起使用它们。我认为 Claims是他们所支持的 Roles的子类别。

例如:
角色: 会计
声明 : CanUpdateLedger,CanOnlyReadLedger,CanDeleteFromLedger < br/>

问: 它们是否打算相互排斥?
问: 还是只索赔并且“完全符合”你的索赔要求更好?
问: 那么这里的最佳实践是什么呢

同时使用角色和声明
当然,您必须为此编写自己的 Attribute 逻辑..。

[Authorize(Roles="Accounting")]
[ClaimAuthorize(Permission="CanUpdateLedger")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here


return View();
}

完全符合你的要求

[ClaimAuthorize(Permission="Accounting.Ledger.CanUpdate")]
public ActionResult CreateAsset(Asset entity)
{
// Do stuff here


return View();
}
47346 次浏览

角色是一个符号类别,它将共享相同级别安全特权的用户聚集在一起。基于角色的授权需要首先识别用户,然后确定分配给用户的角色,最后将这些角色与授权访问资源的角色进行比较。

相反,索赔不是基于组的,而是基于身份的。

来自 Microsoft 文档:

创建标识时,可以为其分配一个或多个由受信任方发出的索赔。声明是一个名称值对,表示主题是什么,而不是主题可以做什么。

稍后,安全检查可以根据一个或多个索赔的值确定访问资源的权限。

You 可以 use both in concert, or use one type in some situations and the other in other situations. It mostly depends on the inter-operation with other systems and your management strategy. For example, it might be easier for a manager to manage a list of users assigned to a role than it is to manage who has a specific Claim assigned. Claims can be very useful in a RESTful scenario where you can assign a claim to a client, and the client can then present the claim for authorization rather than passing the Username and Password for every request.

正如@Claies 完美解释的那样,索赔可以更具描述性,是一种深层次的角色。我认为他们是你们的角色。我有一个健身房的 ID,所以我属于会员的角色。我也在上跆拳道课,所以我有他们的跆拳道身份证。我的申请需要一个新角色的声明,以适应我的会员权利。相反,我为我所属的每个组类使用 id,而不是许多新的成员类型。这就是为什么索赔更适合我。

有一个很好的解释视频 Barry Dorrans,谈论使用声明的优势超过角色。他还指出,角色,仍然存在。网络向下兼容。该视频非常详细地介绍了声明、角色、策略、授权和身份验证的工作方式。

你可以在这里找到它: ASP.NET Core Authorization with Barr Dorrans

几十年来,我使用了各种身份验证和授权技术,现在的 MVC 应用程序使用以下方法。

声明用于所有授权。用户被分配一个角色(可能有多个角色,但我不需要这个)-更多如下。

与通常的做法一样,使用的是  副产品授权属性类。因为大多数控制器操作都是 CRUD,所以我在代码优先的数据库生成中有一个例程,它迭代所有控制器操作,并为 Read/Edit/Create/Delete 的每个控制器操作属性创建索赔类型。例如,

[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]

为了在 MVC 视图中使用,基本控制器类显示视图包项

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user claims
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;


if (user != null)
{
// Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();


// set Viewbag with default authorisations on this controller
ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
}


base.OnActionExecuting(filterContext);
}

对于网站菜单和其他非控制器操作,我有其他声明。例如,用户是否可以查看特定的货币字段。

bool UserHasSpecificClaim(string claimType, string claimValue)
{
// get user claims
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;


if (user != null)
{
// Get the specific claim if any
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}


return false;
}


public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}

那么角色是什么呢?

我有一个表,它将一个角色链接到一组(默认)声明。在设置用户授权时,默认设置是为用户提供其角色的声明。每个用户都可以比默认声明拥有更多或更少的声明。为了使编辑变得简单,索赔列表由控制器和操作(在一行中)显示,然后列出其他索赔。按钮和一些 Javascript 一起用于选择一组操作,以尽量减少选择索赔所需的“单击”。在保存时,将删除用户声明并添加所有选定的声明。Web 应用程序只加载声明一次,因此任何更改都必须提示在此静态数据中重新加载。

因此,管理人员可以选择每个角色中的哪些声明,以及用户在将这些声明设置为一个角色之后拥有哪些声明和那些默认声明。该系统只有少量的用户,因此管理这些数据非常简单

为了理解角色和声明之间的区别,你必须面对角色的限制,感受声明是如何超越这些问题的,所以让我给你两个场景来认识声明的力量,当角色不能解决这些问题的时候:

你的网站有两个模块(页面,服务。.儿童(18岁以下)第一个单元,成人(18岁以上)第二个单元 你的用户身份有一个生日声明

您需要创建一个关于这个索赔的政策,这样每个模块的授权将根据这个值给出,如果用户的年龄超过18岁,那么他可以进入成人模块,而不是在这个年龄之前。

角色的布尔是你能不能拥有这个角色,它没有多重价值。

2-您的网站有角色用户,您想要阻止访问的用户进行一些维护,而不改变代码。

在声明中,可以创建 UnderConstrance 策略,如果为 true,则用户不能查看页面,并为角色用户授权属性。

在写这个答案的时候,我们正处于“ .NET 5.0”和“ .NET 6.0”的转角处。这就是我对所见所闻的理解:

问: 我们不再使用角色了吗?

是的,您不应该再使用 Roles 了(至少不应该像在以前的框架中那样使用它。

问: 如果是这样,为什么角色仍然提供?

使升级项目更容易/更快?

问: 我们应该只使用索赔吗?

是的。但是一定要看看@Jonathan Ramos 在这里发布的回答视频。

问: 我们应该一起使用角色和索赔吗?

不,但是您当然可以将一个角色放入一个索赔中,但是请确保将您的项目升级为仅使用索赔。

您不应该编写自己的属性,而应该使用 政策,因为这是新框架的方式。如果你需要你自己的属性,你“做错了”,只需要创建你自己的需求(处理程序) ,这就是整个“新”策略的意义所在。 在当前的框架中,属性 授权甚至不再可用。