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

问题描述 投票:121回答:10

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

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

asp.net-mvc claims-based-identity access-control role-base-authorization role-based
10个回答
233
投票

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

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

[Authorize(Roles="Sale")]
public ActionResult CreateCustomer()
{
    return View();
}

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

[Authorize(Roles = "Sale", "Marketing")]
public ActionResult CreateCustomer()
{
    return View();
}

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

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

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

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

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

“CanCreateCustomer”,“CanDeleteCustomer”,“CanEditCustomer”等。

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

        [ClaimAuthorize(Permission="CanCreateCustomer")]
        public ActionResult CreateCustomer()
        {
            return View();
        }

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

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

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

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

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


1
投票

我认为这个问题可以从数据库的角度来回答。如果您注意到这种植入所涉及的表格,您会发现以下内容

  1. AspNetUsers:每个用户都有一行,其中包含所有用户所需的所有属性,如电子邮件,地址电话,密码......
  2. AspNetRoles;根据GM,CTO,HRM,ADMIN,EMP等应用要求定义不同的角色。每个角色定义的是根据应用程序的需要。
  3. AspNetUserRoles:每行链接AspNetUsers和AspNetRoles,并有效地链接一个用户和多个角色。
  4. AspNetUserClaims:每行都有AspNetUsers的密钥和一个类型和值。所以有效地为每个用户添加一个属性,可以在运行时添加/删除。

可以在用户/应用程序生命周期的某个时刻调整此表的使用以匹配特定需求。

考虑“采购经理”(PM)的早期阶段,我们可以有三种方法

  1. 应用程序使用一行填充AspNetUserRoles以授予'PM'购买权。要发出任何金额的采购订单,用户只需要“PM”角色。
  2. 应用程序使用一行填充AspNetUserRoles以授予'PM'购买权,并填充AspNetUserClaims声明TYPE'采购金额'类型和“<1000”值以设置金额限制。要发出采购订单,用户需要具有“PM”并且订单金额低于索赔类型“采购金额”的索赔值。
  3. 应用程序填充AspNetUserClaims,声明类型为“采购金额”类型和“<1000”值。任何用户都可以发出采购订单,因为该金额低于此用户的索赔类型“采购金额”的索赔值。

可以注意到,基于角色的粗略权限是粗略的,从系统管理的角度来看,这将简化应用程序用户的生命。但是从业务需求的角度来看,它会限制用户的能力。另一方面,基于声明的是需要分配给每个用户的非常好的权限。声明基础将推动业务的极限,但会使系统管理变得非常复杂。


44
投票

我不完全同意Emran的回答

[Authorize(Roles="Sale")]

太天真了

问题是如何

  [Authorize(Roles="CustomerCreator")]

不同于

 [ClaimAuthorize(Permission="CanCreateCustomer")]

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

我想因为

与Role相比,Claim概念更通用

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

索赔的其他示例。

  1. “AAA”是由“MYExamSite.com”提供的“MYExamSite.Score”类型的索赔
  2. “Gold”是由“MYGYMApp”提供的“MYGYM.Membershiptype”类型的索赔

36
投票

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

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

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

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


28
投票

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

什么是角色

Role =用户和权限的联合。

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

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

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

什么是集团

Group =用户集合

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

什么是权限

许可=主题可以做什么

什么是权限集

权限集=权限集合

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

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

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

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

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

什么是索赔

声明=主题“是什么”

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

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

何时使用索赔

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

@CodingSoft在之前的回答中使用了夜总会的比喻,我想扩展一下。在该答案中,使用驾驶执照作为包含一组索赔的示例,其中出生日期代表其中一项索赔,而DateOfBirth索赔的值用于根据授权规则进行测试。颁发驾驶执照的政府是赋予索赔真实性的权力机构。因此,在夜总会的情况下,门口的保镖会查看该人的驾驶执照,确保它是由受信任的机构发出的,通过检查它是否是假身份证(即必须是有效的政府颁发的身份证),然后查看出生日期(驾驶执照上的许多索赔之一),然后使用该值来确定此人是否足够进入俱乐部。如果是这样,该人通过拥有有效的权利要求而不是通过某种角色来传递授权规则。

现在,考虑到这个基础,我现在想进一步扩展它。假设夜总会所在的建筑物包含办公室,房间,厨房,其他楼层,电梯,地下室等,只有俱乐部的员工才能进入。此外,某些员工可能会访问其他员工可能不会访问的某些地方。例如,经理可以访问其他员工无法访问的办公楼层。在这种情况下,有两个角色。经理和员工。

如上所述,访客进入公共夜总会区域的权利由单一索赔授权,员工需要通过角色访问其他非公共限制房间。对他们来说,驾驶执照是不够的。他们需要的是他们扫描进入门的员工徽章。某处有一个RBAC系统,可以在Manager角色访问顶层时授予徽章,在Employee Role访问其他房间时使用徽章。

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

软件权限

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

最后一点说明。

格兰特vs拒绝

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

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

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

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

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

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

我希望这有帮助。

This is a Diagram of the RBAC Described Above

2019年4月7日更新根据@Brent的反馈(谢谢)...删除了对先前答案的不必要的引用,并解释了@CodingSoft提供的“夜总会”比喻的原始基础,以便在不拥有这个答案的情况下理解阅读其他答案。


7
投票

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

在这里阅读更多:


6
投票

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


5
投票

RBAC和CBAC之间的基础是:

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

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

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


4
投票

在决定哪种方法最佳之前,首先要分析验证所需的内容非常重要。从下面的Microsoft文档中,它说“索赔不是主题可以做的。例如,您可能拥有由当地驾驶执照颁发的驾驶执照。您的驾驶执照上有您的出生日期。在这种情况下索赔名称是DateOfBirth,索赔价值将是您的出生日期,例如1970年6月8日,发行人将是驾驶执照机构。基于索赔的授权,最简单的,检查索赔的价值并允许访问基于该价值的资源。例如,如果您想进入夜总会,授权程序可能是:6“门保安员会评估您的出生日期索赔的价值以及他们是否信任发行人(驾驶执照当局) )在授予您访问权限之前。

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

基于角色的授权https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles 10/14/2016创建身份时,它可能属于一个或多个角色。例如,Tracy可能属于管理员和用户角色,而Scott可能只属于User角色。如何创建和管理这些角色取决于授权过程的后备存储。角色通过ClaimsPrincipal类上的IsInRole方法暴露给开发人员。

基于声明的授权https://docs.microsoft.com/en-us/aspnet/core/security/authorization/claims 10/14/2016当创建身份时,可以为其分配由受信任方发布的一个或多个声明。声明是名称值对,表示主题是什么,而不是主题可以做什么。例如,您可能拥有由当地驾驶执照颁发机构颁发的驾驶执照。您的驾驶执照上有您的出生日期。在这种情况下,索赔名称将是DateOfBirth,索赔值将是您的出生日期,例如1970年6月8日,发行人将是驾驶执照当局。基于声明的授权最简单地检查声明的值,并允许基于该值访问资源。例如,如果您想要访问夜总会,授权过程可能是:

在给予您访问权限之前,门保安员将评估您的出生日期索赔的价值以及他们是否信任发行人(驾驶执照机构)。

标识可以包含多个具有多个值的声明,并且可以包含多个相同类型的声明。


2
投票

还可以以索赔方式管理角色。

不是创建反映业务角色的授权角色,而是创建反映操作角色的角色,例如CreateCustomer,EditCustomer,DeleteCustomer。根据需要注释方法。

将个人映射到一组动作角色并不是一件简单的事情,特别是当角色列表变大时。因此,您需要以较低的粒度级别(例如,销售,市场营销)管理业务角色,并将业务角色映射到所需的操作角色。即,将用户添加到业务角色,并将其映射到现有授权表中的必需(操作)角色。

您甚至可以覆盖业务角色并直接将人员添加到操作角色。

因为您构建的基础已经有效,所以不要撤消现有的授权过程。您只需要几个表来实现此方法

© www.soinside.com 2019 - 2024. All rights reserved.