基于角色与权限的访问控制


44

我试图了解访问控制(授权)时角色和权限之间的固有权衡。

让我们从一个给定的开始:在我们的系统中,“ 权限”将是一个细粒度的访问单位(“ 编辑资源X ”,“ 访问仪表板页面 ”,等等)。一个角色将是1 +权限的集合。一个用户可以具有1个以上的角色。所有这些关系(用户,角色,权限)都存储在数据库中,可以随时根据需要进行更改。

我的担忧:

(1)检查用于访问控制的角色有何“坏处”?通过检查权限可获得什么好处?换句话说,以下这两个摘要有什么区别:

if(SecurityUtils.hasRole(user)) {
    // Grant them access to a feature
}

// vs.
if(SecurityUtils.hasPermission(user)) {
    // Grant them access to a feature
}

和:

(2)在这种情况下,角色甚至可以提供什么有用的价值?我们不能直接为用户分配1+权限吗?角色提供什么抽象的具体价值(有人可以提供具体示例)吗?


2
有两点:(1)一个用户可能有多个角色,(2)您可能希望研究ACL(访问控制列表),例如。您可能希望仅对一部分仪表板页面(如果有几个)授予“访问仪表板页面”的权限。
Matthieu M.

Answers:


62

(1)检查用于访问控制的角色有何“坏处”?通过检查权限可获得什么好处?

在检查时,调用代码只需知道“用户X是否有权执行操作Y?”。
调用代码不关心也不应该知道角色和权限之间的关系。

然后,授权层将通常通过检查用户角色是否具有此权限来检查用户是否具有此权限。这使您可以更改授权逻辑,而无需更新调用代码。

如果直接在呼叫站点检查角色,则将隐式形成角色⇄许可关系,并将授权逻辑注入到调用代码中,从而避免了关注点的分离。

如果您以后决定该角色foo不具有权限baz,则必须更改每个检查用户是否为的代码foo

(2)在这种情况下,角色甚至可以提供什么有用的价值?我们不能直接为用户分配1+权限吗?角色提供什么抽象的具体价值(有人可以提供具体示例)吗?

角色从概念上代表权限的命名集合。

假设您要添加一个新功能,该功能允许用户编辑某些设置。此功能应仅对管理员可用。

如果要存储每个用户的权限,则必须在数据库中查找您以某种方式知道是管理员的所有用户(如果不存储用户的角色信息,您甚至将如何知道哪些用户是管理员?)并追加此权限为其权限列表。

如果使用角色,则只需将权限附加到Administrator角色,这既易于执行,又节省空间,并且不易出错。


嗯 该认证层会检查用户是谁,他声称自己是; 检查哪些功能/数据可以使用户访问的
SJuan76'2015-10-13

4
这对所有程序员来说都是必读的。优秀的。
Kosta Kontos,2015年

2
简单,简洁且切合实际-在某处占据整本书的整个章节。谢谢。
Dan Nissenbaum

2
为了清楚起见,请发表评论(如果我弄错了,请纠正我):一种authorization layer可能的意思仅仅是简单地定义函数(即)user->hasPermission(SOME_PERMISSION)先在内部检查用户的角色,然后检查是否有任何角色包括/排除给定的角色允许。例如,the calling code可能正在检查某个页面是否对用户可见并且将调用user->hasPermission(VIEW_GIVEN_PAGE),并且authorization layer由检查上述角色的函数定义组成hasPermission
Dan Nissenbaum

1
@DanNissenbaum是的,听起来您做对了,就像检查用户角色是否具有此授权一样简单。可能还不止如此。例如,也许您可​​以选择暂时挂起用户,在这种情况下hasPermission可以选中usersRole.HasPermission(VIEW_GIVEN_PAGE) && !user.Suspended。关键是所有步骤都在一个地方完成,而不是在使用(调用)代码中完成。
Rotem'1

18

在回答您的第一个问题时,检查用户具有角色而不是特定权限的最大问题是权限可以由多个角色持有。例如,开发人员可以访问公司内部网上的开发人员门户,这也可能是其经理持有的许可。如果用户随后尝试访问开发人员门户,则将出现类似于以下内容的检查:

if(SecurityUtils.hasRole(developer)) {
    // Grant them access to a feature
} else if(SecurityUtils.hasRole(manager)) {
    // Grant them access to a feature
} else if...

switch用您选择的语言做的陈述会更好,但仍然不是特别整洁)

权限越常见或拥有的权限越广,您将需要检查的用户角色越多,以确保某人能够访问给定的系统。这也将导致以下问题:每次您修改角色权限时,都需要修改检查以反映这一点。在大型系统中,这将很快变得非常笨拙。

例如,如果仅检查用户是否具有允许他们访问开发人员门户的权限,则不管他们担任什么角色都将被授予访问权限。

要回答第二个问题,您拥有角色的原因是因为它们很容易修改和分发权限的“程序包”。如果您拥有一个具有数百个角色和数千个权限的系统,则添加新用户(例如,新的HR经理)将要求您仔细检查并赋予他们其他HR经理所拥有的所有权限。这样做不仅繁琐,而且如果手动进行也容易出错。相比之下,只需将“ HR Manager”角色添加到用户的个人资料即可,这将授予他们与具有该角色的其他所有用户相同的访问权限。

您可能会争辩说,您可以简单地克隆一个现有用户(如果您的系统支持此功能),尽管这样做确实为该用户授予了该时间段的正确权限,但将来可能会尝试为所有用户添加或删除权限难。这种情况的一个示例场景是,如果过去可能是人力资源人员也负责工资单,但后来公司变得足够大,可以专门雇用员工来处理工资单。这意味着HR不再需要访问薪资系统,因此可以删除权限。如果您有10个不同的HR成员,则需要手动检查并确保删除正确的权限,否则可能会导致用户错误。另一个问题是,它根本无法扩展。随着您在给定角色中获得越来越多的用户,这将使角色修改变得更加困难。将其与使用角色进行比较,使用角色时,您只需要修改所讨论的总体角色以删除权限,这将由拥有该角色的每个用户反映出来。


很好的例子,谢谢!
坦率
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.