我对claims
中ASP.NETIdentity
的使用完全不熟悉,并希望了解使用Roles and/or Claims
的最佳做法。
在完成所有这些阅读之后,我仍然有类似的问题......
问:我们不再使用角色了吗? 问:如果是这样,为什么Roles仍然提供? 问:我们应该只使用索赔吗? 问:我们应该使用Roles&一起索赔?我最初的想法是,我们应该"应该"一起使用它们。我将Claims
视为他们支持的Roles
的子类别。
例如:
角色:会计
声明:CanUpdateLedger,CanOnlyReadLedger,CanDeleteFromLedger
示例:使用角色&一起索赔
当然,您必须为此编写自己的属性逻辑...
[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();
}
答案 0 :(得分:70)
角色是一种符号类别,它将收集共享相同级别安全权限的用户收集在一起。基于角色的授权需要首先识别用户,然后确定用户被分配到的角色,最后将这些角色与有权访问资源的角色进行比较。
相反,声明是用户识别自己的权利。换句话说,"我被允许这样做,因为我有这个要求。"。通常,基于声明的授权包含基于角色的授权。确切地说,角色成员资格是根据身份确定的,而身份只是对权利要求价值的一种权利。角色本质上是一种非常特殊的声明,即"因为我的用户名就是这个,所以我是这个角色的成员。因为我是此角色的成员,所以我可以访问此资源。"。
你可以同时使用两者,或者在某些情况下使用一种类型,在其他情况下使用另一种类型。它主要取决于与其他系统的互操作性和您的管理策略。例如,管理员管理分配给角色的用户列表可能比管理分配了特定索赔的用户更容易。声明在RESTful场景中非常有用,您可以在其中为客户端分配声明,然后客户端可以提出声明以进行授权,而不是为每个请求传递用户名和密码。
答案 1 :(得分:21)
正如@Claies完美解释的那样,声明可能更具描述性,是一种深层次的角色。我认为它们是你的角色ID。我有健身房,所以我属于会员角色。我也参加了跆拳道课程,所以我对他们有所要求;一个跆拳道ID。我的申请需要申报新角色以适应我的会员权利。相反,我在健身房可以做的每件特别事情都有ids;而不是许多新的会员类型。这就是为什么声称适合我。
Barry Dorrans有一个很棒的解释视频,谈论使用声明而非角色的优势。他还声明角色仍然在.NET中以实现向后兼容。该视频非常了解声明,角色,政策,授权和身份验证的工作方式。
答案 2 :(得分:5)
几十年来,我使用了各种身份验证和授权技术,目前的MVC应用程序使用以下方法。
声明用于所有授权。为用户分配了一个角色(可能有多个角色但我不需要这个角色) - 更多信息如下。
通常的做法是使用ClaimsAuthorize属性类。由于大多数控制器操作都是CRUD,因此我在代码优先数据库生成中有一个例程,它迭代所有控制器操作,并为读取/编辑/创建/删除的每个控制器操作属性创建声明类型。例如。从,
[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应用程序仅加载一次声明,因此任何更改都必须在此静态数据中提示重新加载。
管理员因此可以选择每个角色中的哪些声明以及用户在将其设置为角色后声明哪些声明以及这些声明。系统只有少量用户,因此管理这些数据非常简单
答案 3 :(得分:1)
要了解角色和声明之间的区别,您要面对角色的局限性并感觉到声明如何解决此问题,因此我给您提供了两种方案,以认识到角色无法解决此问题的声明的作用:< / p>
1-您的站点有两个模块(页面,服务等),第一个模块针对儿童(18岁以下),另一个模块针对成人(18岁以上) 您的用户身份有生日要求
您需要为此声明制定政策,以便每个模块的授权都将基于此值给出,如果用户的年龄超过18岁,那么他可以进入成人模块,而不是此年龄之前
角色是您可以具有或没有角色的布尔数据类型 角色没有恶意值
2-您的站点具有角色用户,并且您将不阻止用户访问以在不更改代码的情况下进行一些维护
在声明中,您可以创建UnderConstrain策略,如果真实用户无法查看页面,则为角色用户授予属性授权。
答案 4 :(得分:0)
在撰写此答案时,我们正处于“.NET 5.0”阶段,“.NET 6.0”即将到来。这是我对所见所闻的理解:
<块引用>问:我们不再使用角色了吗?
是的,您不应该再使用角色(至少不是您在以前的框架中使用的方式。
<块引用>问:如果是这样,为什么仍然提供角色?
让升级项目更容易/更快?
<块引用>问:我们应该只使用 Claims 吗?
是的。但请务必查看@Jonathan Ramos 在此处发布的视频。
<块引用>问:我们应该一起使用角色和声明吗?
不可以,但您当然可以将角色放入声明中,但一定要升级您的项目以仅使用声明。
而且你不应该编写你自己的属性,你应该使用policy,因为这是新框架的方式。如果你需要你自己的属性你“做错了”,只需创建你自己的 Requirement(handler) 这就是整个“新”政策的全部内容。 在当前框架中,ClaimAuthorize 属性甚至不再可用。