ASP.NET MVC中基于角色的访问控制(RBAC)与基于声明的访问控制(CBAC)

Mr.*_*kin 129 asp.net-mvc access-control claims-based-identity role-based role-base-authorization

使用CBACRBAC的主要好处是什么?何时使用CBAC更好,何时使用RBAC更好?

我试图理解CBAC模型的一般概念,但总体思路对我来说仍然不明确.

Emr*_*ain 241

我将尝试展示如何从ASP.NET MVC上下文中的基于声明的访问控制中受益.

当您使用基于角色的身份验证时,如果您有创建客户的操作,并且您希望处于"销售"角色的人员能够执行此操作,那么您可以编写如下代码:

[Authorize(Roles="Sale")]
public ActionResult CreateCustomer()
{
    return View();
}
Run Code Online (Sandbox Code Playgroud)

后来,您意识到,有时来自"营销"角色的人员应该能够创建客户.然后,您更新您的Action方法

[Authorize(Roles = "Sale", "Marketing")]
public ActionResult CreateCustomer()
{
    return View();
}
Run Code Online (Sandbox Code Playgroud)

现在,您意识到,一些营销人员必须无法创建客户,但不可能为营销人员分配不同的角色.因此,您被迫允许所有营销人员创建客户.

你发现了另一个问题,每当你决定允许营销人员创建客户时,你必须更新你的所有MVC Action方法Authorize属性,编译你的应用程序,测试和部署.几天后,你决定,而不是营销而是一些其他的角色应该被允许做任务,让你在你的代码库搜索和删除授权属性的所有"营销"和授权的属性添加新角色的名字...这不是个健康解决方案 此时,您将意识到需要基于权限的访问控制.

基于权限的访问控制是一种为各种用户分配各种权限并检查用户是否有权在运行时从代码执行操作的方法.在为各种用户分配各种权限后,您意识到如果用户具有"Facebook用户","长时间用户"等属性,则需要允许某些用户执行某些代码.让我举个例子.假设您希望在用户使用Facebook登录时允许访问特定页面.现在,您是否会为该用户创建"Facebook"权限?不,'Facebook'听起来不像是一种许可.可以 ?相反,它听起来像是一种说法.与此同时,权限听起来也像索赔!因此,最好检查声明并允许访问.

现在,让我们回到基于声明的访问控制的具体示例.

您可以像这样定义一组声明:

"CanCreateCustomer","CanDeleteCustomer","CanEditCustomer"等.

现在,您可以像这样装饰您的Action方法:

        [ClaimAuthorize(Permission="CanCreateCustomer")]
        public ActionResult CreateCustomer()
        {
            return View();
        }
Run Code Online (Sandbox Code Playgroud)

(请注意,[ClaimAuthorize(Permission ="CanCreateCustomer")]可能没有内置到MVC类库中,我只是作为一个例子展示,你可以使用一些具有这种Attribute类定义的类库)

现在,您可以看到,CreateCustomer操作方法将始终需要权限'CanCreateCustomer',它将永远不会更改或几乎不会更改.因此,在您的数据库中,您创建一个权限表(声明)和用户权限关系.在管理面板中,您可以为每个可以执行操作的用户设置权限(声明).您可以将"CanCreateCustomer"权限(声明)分配给您喜欢的任何人,并且只允许用户能够创建客户,并且允许的用户将只能创建客户而不能创建其他任何内容(除非您为同一用户分配其他权限).

此安全模型为您提供干净的代码实践.此外,当您编写Action方法时,您不必考虑谁可以使用此方法,而是始终可以确保使用此方法的任何人都将获得管理员提供的适当权限(声明).然后,管理员可以决定谁将能够做什么.不是你作为开发人员.这就是你的业务逻辑如何与安全逻辑分离.

每当有人迹象,您的应用程序会检查任何权限可供用户和权限(要求)集将作为登录用户的当前附加属性(通常要求设置存储为cookie中登录的用户),所以你不必一直检查数据库中的权限集.最重要的是,如果您应用基于声明的访问而不是基于角色的访问,则可以更好地控制应用程序中的安全逻辑.实际上,角色也可以被视为一种声明.

如果您的应用程序是一个非常小的应用程序,其中只有两个角色:客户和管理员,除了他们在您的应用程序中的意图之外,客户不可能做任何其他事情,那么也许,基于角色访问控制将用于此目的,但随着应用程序的增长,您将开始在某个时刻感觉到需要基于声明的访问控制.

  • 哇,我一直试图弄清楚整个声称的事情是如何起作用的,但我从未理解所有模糊的抽象解释和例子.你的帖子是第一个打开我的脑海并传达信息的帖子.非常感谢您解释它如此简洁. (7认同)
  • 我感到困惑的是角色如何考虑到声明 - 基于声明的系统角色基本上不是一组声明,以便您可以批量分配内容?例如,你可以说Bob扮演营销角色,营销部门的每个人都声称"CanCreateCustomer,CanViewAdCampaigns" (6认同)
  • 假设我想这样:1)"许可"是做一个简单操作的权利,比如"创建客户".权限的名称以"can"开头--CanCreateCustomer.权限的名称在应用程序的源代码中是硬编码的.2)可以为用户分配一组权限 - 但不能直接分配.用户仅通过角色接收权限.3)角色是一组权限,仅此而已.一些最终用户(管理员)可以使用任意设置的od权限(从固定列表中选择)动态创建新的自定义角色.问题是:我能否使用基于声明的模型做到这一点? (5认同)
  • Microsoft文档说:声明是名称值对,表示主题是什么,而不是主题可以做什么. (4认同)
  • 这是一个非常深思熟虑的解释,但我认为你认为它的评论是不完整的"差异在于概念,而不是技术." 实际上技术存在差异,这个答案没有解决.简而言之,我不同意它取决于你如何定义角色,因为这两种技术满足了非常不同的要求.我不愿提供更正,因为答案本身对于演示与应用过于宽泛的授权角色(或声明)相关的陷阱非常有帮助.不幸的是,这不是问题. (3认同)
  • 嗨乔治,这取决于你如何在你的系统中定义ROLE.您可以定义听起来像权限或声明的角色.这种方法不会阻止你实现同样的目标.角色通常意味着"任命"; 这就是使用术语的方式.区别在于概念,而不是技术.如果你有像"CanCreateCustomer"这样的角色,那么它在抽象意义上将类似于CBAC.争论的焦点是你是否应该在安全模型中创建约会或微权限.声明不只是关于权限,它提供更多.即,你可以拥有Facebook /谷歌用户的索赔等. (2认同)

Pus*_*dra 45

我不完全同意Emran的回答

[Authorize(Roles="Sale")]
Run Code Online (Sandbox Code Playgroud)

太天真了

问题是如何

  [Authorize(Roles="CustomerCreator")]
Run Code Online (Sandbox Code Playgroud)

不同于

 [ClaimAuthorize(Permission="CanCreateCustomer")]
Run Code Online (Sandbox Code Playgroud)

如果两者同样好,为什么我们需要索赔?

我想因为

与Role相比,Claim概念更通用

在上面的示例中,我们可以说"CustomerCreator"是"Asp.NETroleProvider"提供的"角色"类型的声明

索赔的其他示例.

  1. "AAA"是由"MYExamSite.com"提供的"MYExamSite.Score"类型的索赔

  2. "Gold"是由"MYGYMApp"提供的"MYGYM.Membershiptype"类型的索赔

  • 我认为这个答案具有价值,因为它解决了声明与其等效角色之间的根本区别,而不是描述可以使用声明或基于角色的授权模型有效实现的场景.+1 (8认同)
  • 我已经对我的回答发表了评论。我说,这取决于您如何定义组织中的“角色”。您可以定义一个听起来像 Permission / 或 claim 的角色。这种方法不会阻止您实现相同的目标。ROLE 通常表示“约会”;这就是所使用的术语的使用方式。区别在于概念,而不是技术。如果您使用的是 [Authorize(Roles="CustomerCreator")],那么它在抽象意义上类似于 CBAC。争论的焦点是您是否应该在安全模型中创建约会或 Mico 权限。声明不仅仅是关于权限,它提供了更多。 (2认同)

Ric*_*rdo 40

我现在已多次实施安全模型,并且不得不围绕这些概念.做了很多次,这是我对这些概念的理解.

什么是角色

先前答案中给出的角色定义不正确......或者说它们不完整.

Role = 用户和权限的联合.

一方面,角色是权限的集合.我喜欢称之为权限配置文件.在定义角色时,您基本上会向该角色添加一堆权限,因此在这种意义上,角色是权限配置文件.

另一方面,角色也是用户的集合.如果我将Bob和Alice添加到角色"Managers",那么"Managers"现在包含两个用户类似于Group的集合.

事实是,角色既是用户集合,又是一组权限集合在一起.在视觉上,这可以被视为维恩图.

什么是集团

Group =用户集合

"组"严格地是用户的集合.组和角色之间的区别在于角色还具有权限集合,但组仅具有用户集合.

什么是权限

许可=主题可以做什么

什么是权限集

权限集=权限集合

在强大的RBAC系统中,权限也可以像用户一样进行分组.尽管组是仅用户的集合,但权限集仅是权限集合.这允许管理员一次向角色添加权限的整个集合.

用户,组,角色和权限如何结合在一起

在健壮的RBAC系统中,可以单独将用户添加到角色以创建角色中的用户集合,或者可以将组添加到角色,以便一次向角色添加用户集合.无论哪种方式,角色都可以单独添加其用户集合,或者通过向角色添加组或向角色添加用户和组的组合.可以以相同的方式考虑权限.

可以将权限单独添加到角色以创建角色内的权限集合,也可以将权限集添加到角色.最后,可以将权限和权限集的混合添加到角色.无论哪种方式,角色都会单独添加其权限集合,或者通过向角色添加权限集.

角色的整个目的是将用户与权限结合.因此,角色是用户和权限的联合.

什么是索赔

声明=主题"是什么"

声明不是权限.正如之前的答案中所指出的,索赔是主体"不是"主题"可以做"的内容.

声明不会替换角色或权限,它们是可用于制定授权决策的其他信息.

何时使用索赔

我发现当无法将用户添加到角色或者决策不是基于用户与权限的关联时,需要进行授权决策时声明有用.Facebook用户的例子导致了这一点.Facebook用户可能不是添加到"角色"的人...他们只是通过Facebook验证的一些访问者.虽然它不能完全适合RBAC,但它是一条信息来做出授权决定.

要使用夜总会比喻,包含出生日期索赔的驾驶执照"授权"访客进入俱乐部.这是对属性的价值(即DoB = {MM-DD-YYYY})做出的决定,以及由受信任的机构(即政府发布)提出索赔的事实.

然而,夜总会所在的建筑物可能包含办公室,房间,厨房,其他楼层,电梯,地下室等,只有俱乐部的员工才能进入.此外,某些员工可能会访问其他员工可能不会访问的某些地方.例如,经理可以访问其他员工无法访问的办公楼层.在这种情况下,有两个角色.经理和员工.

虽然访客进入公共夜总会区域只需一次索赔,但员工需要通过角色访问.对他们来说,驾驶执照是不够的.他们需要的是他们扫描进入门的员工徽章.某处有一个RBAC系统,可以在Manager角色访问顶层时授予徽章,在Employee Role访问其他房间时使用徽章.

如果出于某种原因需要通过Role添加/删除某些房间,这可以使用RBAC完成,但它不适合索赔.

软件权限

我同意之前的答案,将角色编码到应用程序中是一个坏主意.这将角色的目的硬编码到应用程序中.应用程序应该具有的功能就像功能标志一样.在通过配置可访问功能标志的情况下,权限可由用户安全上下文访问,该上下文是由用户所在的所有角色收集的DISTINCT权限集合派生的.这就是我所说的"有效权限".应用程序应该只显示功能/操作的可能权限菜单.RBAC系统应该通过角色将这些权限与用户结合起来.这样,没有角色的硬编码,并且唯一一次权限更改是删除它或添加新的.一旦将权限添加到软件中,就不应该更改它.它只应在必要时删除(即在新版本中停用某个功能时),并且只能添加新功能.

最后一点说明.

格兰特vs拒绝

一个强大的RBAC系统甚至CBAC系统应该区分Grants和Denials.

添加角色权限应该附带GRANT或DENY.选中权限后,应将所有GRANTed权限添加到有效权限的用户列表中.完成所有操作后,DENIED权限列表应该导致系统从有效权限列表中删除这些权限.

这允许管理员"调整"主题的最终权限.最好还可以直接将权限添加到用户.这样,您可以将用户添加到管理员角色,并且他们可以访问所有内容,但是您可能想要拒绝访问Lady's Restroom,因为用户是男性.因此,您将男性用户添加到管理员角色,并使用DENY向User对象添加权限,这样只会取消Lady的房间访问权限.

实际上,这将是索赔的一个很好的候选人.如果用户有"性别=男性"的声明,那么在"管理员角色"中可以访问所有房间,但是女士的洗手间也要求声明性别=女性,男士洗手间要求声明性别=男性.通过这种方式,人们不必为男性用户配置DENY权限,因为声明强制执行会为具有单个授权规则的每个人负责.但是,它可以以任何一种方式完成.

关键在于,通过DENIAL of Permissions,它可以更轻松地管理角色,因为可以实现异常.

下面是我很久以前做的图表,显示了RBAC模型.我没有索赔的图形,但您可以想象它们只是附加到用户的属性,无论它们在哪里.此外,该图不显示组(我需要在某些时候更新它).

我希望这有帮助.

这是上面描述的RBAC图

  • 这是一个很棒的解释,应该添加到顶部,谢谢您添加示例和图表。 (2认同)
  • 很好的答案。一项建议是删除对其他答案的引用。每个答案都应该独立存在,虽然我阅读了其他答案,但并不是每个人都会。 (2认同)
  • 这太棒了,并且用正常的语言进行了解释 - 谢谢 (2认同)

hem*_*emp 39

接受的答案似乎将角色定位为一个钝器,声称是一个灵活的工具,但除此之外,它们看起来几乎相同.不幸的是,这种定位对索赔的概念不利,可能从根本上反映出对其目的的轻微误解.

角色存在并且仅在隐式范围内有意义.通常,这是应用程序或组织范围(即Role = Administrator).另一方面,索赔可由任何人"制造".例如,Google身份验证可能会产生包含用户"电子邮件"的声明,从而将该电子邮件附加到身份.Google提出索赔,该应用程序选择是否理解并接受该声明.应用程序本身可能随后附加一个名为"authenticationmethod"的声明(如ASP.NET MVC Core Identity所做),其值为"Google".每个声明都包含一个范围,以便可以识别声明是否具有外部,本地或两者的含义(或根据需要更细粒度).

关键点是所有声明都明确附加到身份并包含明确的范围.这些声明当然可以用于授权 - 而ASP.NET MVC通过Authorize属性提供对它的支持,但这不是声明的唯一或必然的主要目的.它当然没有区别于Roles,它可以以完全相同的方式用于本地范围的授权.

因此,只要这些角色和声明属于本地作用域,就可以选择使用角色或声明或两者来进行授权,并且可能没有找到任何固有的优点或缺点.但是,如果授权依赖于外部身份声明,那么角色将是不充分的.您必须接受外部声明并将其转换为本地范围的角色.这没有什么不妥,但它引入了一层间接并丢弃了上下文.

  • 很好的答案......我想*我理解你......但是如果你能提供一些具体的例子(可能在ASP MVC上下文中)会更清楚......答案太抽象我很难包装我的头围着它. (2认同)
  • 第二段确实包含了一个与 ASP.NET MVC Core Identity 和 Google 身份验证相关的具体示例。听起来更详细的 Core 新模型演练会有所帮助 - 为此我推荐这篇文章:https://andrewlock.net/introduction-to-authentication-with-asp-net-core/ (2认同)

Cod*_*oft 8

在决定哪种方法最好之前,首先分析需要什么身份验证是很重要的。从基于声明的授权

声明不是主体可以做的。例如,您可能拥有当地驾驶执照当局颁发的驾驶执照。您的驾照上有您的出生日期。在这种情况下,索赔名称将是 DateOfBirth,索赔价值将是您的出生日期,例如 1970 年 6 月 8 日,颁发者将是驾驶执照当局。最简单的基于声明的授权检查声明的值并允许基于该值访问资源。例如,如果您想进入夜总会,授权过程可能是:

门安全员会在授予您访问权限之前评估您的出生日期声明的价值以及他们是否信任颁发者(驾驶执照当局)。

从这个例子中我们可以看到,使用基于声明的授权访问夜总会与在夜总会工作的员工所需的授权类型不同,在这种情况下夜总会的工作人员将需要夜总会访客不需要基于角色的授权,因为夜总会访客在夜总会都有一个共同的目的,因此在这种情况下,基于索赔的授权适用于夜总会访客。

基于角色的授权

创建身份时,它可能属于一个或多个角色。例如,Tracy 可能属于管理员和用户角色,而 Scott 可能只属于用户角色。如何创建和管理这些角色取决于授权过程的后备存储。角色通过 ClaimsPrincipal 类上的 IsInRole 方法向开发人员公开。


Teo*_*ahi 8

如果你想要一个现实生活中的例子;

您有一个学校系统,教师可以登录并查看他们的学生。这些老师处于“老师”的角色。但我们不希望所有的老师都能看到所有的学生,所以我们需要区分同一级别的人及其主张。

  1. Mary - 数学老师(声称:数学)-> 只能看到数学学生
  2. John - 物理老师(声称:物理)-> 只能看到物理学生
  3. Adam - 物理和化学老师(声称:物理、化学)-> 可以看到物理和化学学生。

这三位老师虽然都是老师,但只能看到有相应主张的学生。

还有一位校长,他的名字叫迈克:

  1. Mike - 校长(角色:管理员,声明:不适用)-> 可以查看和管理所有学生,因为他处于管理员角色之下,无论他没有任何声明。

如果我们需要区分管理员级别的人员,我们可以为每个人分配相关的声明。


Dav*_*ard 7

更广泛地说,您应该考虑基于属性的访问控制(ABAC).RBAC和ABAC都是由美国国家标准与技术研究院NIST定义的概念.另一方面,CBAC是微软推出的模型,与ABAC非常相似.

在这里阅读更多:

  • 虽然建议使用基于属性的访问控制很好.在MVC/WebAPI堆栈中实现这些的常见/最佳实践的链接将是很好的.谢谢 (3认同)

Ven*_*idu 6

角色只是索赔的一种。这样,可以有许多其他声明类型,例如,用户名是声明类型之一


Ben*_*yen 5

RBAC和CBAC之间的基础是:

RBAC:必须将用户分配给有权执行操作的角色.

CBAC:用户必须具有正确值,如应用程序所预期的那样,才能获得授权.基于声明的访问控制具有优雅的编写和易于维护.

除此之外,由您的应用程序(依赖方)信任的发布授权服务(安全服务令牌STS)向应用程序发出索赔.