为Web应用程序实现细粒度授权的最佳方法?

时间:2008-11-10 22:33:39

标签: ruby-on-rails web-applications authorization

我正在开发一个Rails Web应用程序,它目前被大约20个用户使用。

应用程序的某些部分只能由某些用户访问,因此我们已经有了一个基本的授权框架,我使用acts_as_authenticated插件实现了该框架。

用户的权限取决于他们在哪个部门工作,因此例如管理可以访问应用程序的所有部分,而会计只能访问与会计相关的部分,而销售只能访问与销售相关的部分等等。

另一方面,用户会看到指向他们没有特权的操作的链接。例如,销售部门的人员会在主菜单中看到指向财务记录的链接,但是当他们点击它时,没有任何反应。这是因为AFAIK没有使用acts_as_authenticated查询用户权限的有效方法。

我想以两种方式改变这种情况:

  1. 我想介绍更细粒度的授权。目前,授权在控制器级别完成。我想在动作或模型级别执行此操作。例如,我希望销售部门的人能够创建和更新付款,但不能删除它们。

  2. 我希望能够有效地查询用户权限,这样我就可以从界面中删除不必要的(并且令人困惑的)链接。

  3. 您认为实施此方法的最佳方式是什么?

    Rails特定的答案不是必需的,我只是想知道如何在数据驱动的应用程序中实现它。

    最后,这是目前的实施方式:

    def authorized?
      current_user.role.foo? or current_user.role.bar?
    end
    

    这是我最初的想法,我认为这不是解决这个问题的最佳方法:

    +------------+------------+---------+
    | department | controller | action  |
    +------------+------------+---------+
    | accounting | payments   | index   |
    | accounting | payments   | new     |
    | accounting | payments   | create  |
    | accounting | payments   | edit    |
    | accounting | payments   | update  |
    | accounting | payments   | destroy |
    | sales      | payments   | new     |
    | sales      | payments   | create  |
    | sales      | payments   | edit    |
    | sales      | payments   | update  |
    +------------+------------+---------+
    

    +------------+----------+-------+--------+------+--------+--------+
    | department | model    | list  | create | read | update | delete |
    +------------+----------+-------+--------+------+--------+--------+
    | accounting | payments | TRUE  | TRUE   | TRUE | TRUE   | TRUE   |
    | sales      | payments | FALSE | TRUE   | TRUE | TRUE   | FALSE  |
    +------------+----------+-------+--------+------+--------+--------+
    

3 个答案:

答案 0 :(得分:3)

根据我的理解,授权的基本概念是一个角色。 角色可以表达各种各样的事情:

  1. 用户与整个系统的关系(例如,成为系统的管理员)
  2. 用户与某种实体的关系(例如,成为评论的主持人)
  3. 用户与某个特定实体的关系(例如,成为某个资源的所有者)
  4. 一些其他复杂的关系(例如,成为某个资源所有者的朋友)
  5. 该用户具有某些属性或以某种特定方式响应某些消息(例如,成为青少年)
  6. 非常精细的授权系统应该允许您根据上述任何标准为用户定义角色。此外,它应该允许您为用户设置多个角色。 (Rails最简单的授权插件形式通常允许您只定义第一种角色,并为用户设置一个角色。)

    授权的另一部分是一种机制,如果用户适合某个角色(角色集),则根据事实决定运行(或不运行)代码的哪一部分。要应用此机制,我们必须找到授权应该发生的点,并选择代码应该或不应该运行的角色。

    在Rails中对我有用的方法是在模型级别定义角色并保留授权机制(为我想要授权的代码部分设置允许的角色,并询问当前用户是否具有允许的角色完全为控制器/视图运行部分。

    为此我使用调整的rails-authorization-plugin,它具有我刚才提到的所有可能性(各种角色,一个用户的许多角色,控制器和视图级别的授权)。

答案 1 :(得分:0)

您可能需要在模型中引入“功能点”或“功能”的概念作为访问控制点; “要素”可能具有可选的“父要素”以形成层次结构。您可以决定什么是功能,哪些不是功能,并以编程方式检查权限。这还应该允许您在绘制菜单之前检查功能级别的访问权限,以便用户永远不会看到指向不允许访问的页面的链接。

描述了类似的情况/解决方案here

答案 2 :(得分:0)

在您的两个提案中,第一个选项看起来更好一点,因为它允许您添加可能不是模型级操作的操作。我猜你会遇到第二个模型做得不够的情况,你需要更改架构或在整个应用程序中开始使用权限逻辑(例如“没有'创建'访问权限的用户也无法运行方法xxx“)

我认为解决方案看起来不太干的原因是重复:

  1. 在部门名称中,
  2. 在部门能力
  3. 关于#1,创建一个department表并给每个部门一个Id是有意义的。

    关于#2,我同意第一条评论。您可以将各种控制器和操作集群到功能组中,然后在用户和功能之间设置多对多关系(映射表)。然后,函数与它们允许的动作/控制器具有一对多的关系。这会让你以最小的重复次数说出“会计和销售应该能够阅读所有财务表格”。