【问题标题】:Generating a list of permissions [duplicate]生成权限列表[重复]
【发布时间】:2013-04-27 03:46:28
【问题描述】:

我正在开发一个完全出于娱乐和教育目的的自定义框架。我已经阅读了this question 关于如何实现权限的内容,我喜欢这些答案;使用装饰器模式和/或根据调度程序的 URL 检查权限。

我的问题是应该如何生成权限白名单?我不希望我的控制器中的 每个 方法都需要执行权限,因此我可以使用特殊的命名约定,例如在方法名称前加上“x”:

class CalendarController
{
    public function index($year = null, $month = null, $day = null)
    {
        // display calendar (no permission needed)
    }

    public function xAddEvent()
    {
        // display form to add event (permission required)
    }

    public function xAddEventSubmit()
    {
        // submit form to add event (permission required)
    }
}

然后我可以编写一个脚本来遍历我的所有控制器并返回 x 方法,给我分配给不同角色的权限列表。

另一种选择是将权限硬编码为每个控制器的属性,例如:

class CalendarController
{
    public $permissions = array('addEvent',
                                'addEventSubmit');

    public function index($year = null, $month = null, $day = null)
    {
        // display calendar (no permission needed)
    }


    public function addEvent()
    {
        // display form to add event (permission required)
    }

    public function addEventSubmit()
    {
        // submit form to add event (permission required)
    }
}

有没有更好的选择,或者我是否走在正确的轨道上?

【问题讨论】:

  • @tereško 我在第一段中链接到那篇文章。它没有解决我的问题。
  • 对不起.. 错过了。不过,您的两个示例似乎都将 ACL 的负担放在您的控制器上。访问权限应存储在您的控制器之外。我会使用一些“config/permissions.php”文件。还要记住,在某些系统中,您需要提供 GUI(如在不同的 CMS 中)来管理其中的一些权限。
  • @tereško 是的,这正是我想要做的。我想为我的管理页面生成权限列表。问题是如何以有效的方式生成该列表。我倾向于抓取控制器的原因是避免在其他地方硬编码权限。 “角色”将存储在数据库中,但附加到这些角色的“权限”是我试图在此处动态列出的内容。

标签: php oop model-view-controller acl rbac


【解决方案1】:

注意:这主要是对我在链接文章中提供的解决方案的扩展。我不会评论hakre的答案。

据我了解您的问题,问题基本上是您不想分别为每种方法设置访问权限。

选项 1:不装饰

在涉及 Decorator 的解决方案中,其中一个好处是,当您使用安全类(例如 Controller,尽管它可以是应用程序的任何部分)时,您不需要知道它已经被装饰了。因此,如果您有一些任何人都应该可以完全访问的控制器,那么您可以不装饰它们。

这种方法很可能需要负责实例化控制器的工厂拥有一些应该或不应该包装在装饰器中的控制器列表。由于这始终需要if 语句来查阅列表,因此我个人只会在您调用多个方法的情况下考虑这种情况(在我的情况下,将不包括控制器)。

选项 2:通配符和白名单

解决此问题的另一种方法是利用您实际检查授权的方式。

$command = [ get_class($this->target), $method ];

这是被检查的令牌。这意味着 ACL 不仅接收方法名,还接收完整的类名(包括命名空间,顺便说一句)。它使您有机会创建一个包含类名和方法名的规则列表。大致如下:

Controllers\Identification::*  anonymous
Controllers\*::*               admin
Controllers\Users::view        authenticated
Controllers\Users::remove      manager
Controllers\Users::add         manager

这个想法是您保存一些配置来定义所有允许的交互。 ACL 在列表中向下,检查用户的组,并在第一次匹配时返回结果(在示例中,管理员可以访问除登录页面之外的所有内容,仅允许未经身份验证的用户使用)。再说一次,这个特定的示例将取决于您至少实现部分组包含组功能。

我还要重申,您应该只为此使用白名单。如果您忘记允许管理员删除用户,不会增加任何重大风险,但是,如果您忘记拒绝用户删除其他用户,则在使用基于黑名单的授权时可能会出现严重错误。

我的两分钱

【讨论】:

    【解决方案2】:

    你有没有想过method overloading?这是一个非常简单的例子。基本上,如果找不到函数,则使用__call() 函数来捕获它。然后,您可以进行权限检查并调用正确的私有或受保护方法。

    class CalendarController
    {
        public function index($year = null, $month = null, $day = null)
        {
            // display calendar (no permission needed)
        }
    
        public function __call($name, $arguments)
        {
            // do your permission checks here
            if ($name == 'addEvent' && $this->hasPermission()) {
                return $this->_addEvent($arguments);
            }
    
            return false;
        }
    
        protected function _addEvent($params) {
    
        }
    }
    

    【讨论】:

      【解决方案3】:

      我建议查看其他框架以了解它们如何实施限制。例如,yii 根据请求的特定操作以及用户是否具有特定级别的权限来实施访问限制。我强烈推荐 RBAC (http://en.wikipedia.org/wiki/Role-based_access_control)

      Yii 示例:

      public function accessRules()
      {
          return array(
              array('allow',  // allow all users to perform 'list' and 'show' actions
                  'actions'=>array('list','show'),
                  'users'=>array('*'),
              ),
              array('allow', // allow authenticated user to perform 'create' and 'update' actions
                  'actions'=>array('create','update'),
                  'users'=>array('@'),
              ),
              array('allow', // allow admin user to perform 'admin' and 'delete' actions
                  'actions'=>array('admin','delete'),
                  'users'=>array('admin'),
              ),
              array('deny',  // deny all users
                  'users'=>array('*'),
              ),
          );
      }
      

      它们还实现了过滤器,告诉我们某些类型的 HTTP 请求必须请求某些操作。以下示例说明为了运行创建操作,HTTP 请求必须是 POST。

      public function filters()
      {
          return array(
              'accessControl', // perform access control for CRUD operations
              'postOnly + create', // we only allow create via POST request
          );
      }
      

      资源:http://www.larryullman.com/2010/01/14/yii-framework-access-control-lists/

      另见:http://www.yiiframework.com/wiki/169/configuring-controller-access-rules-to-default-deny/

      【讨论】:

      • 这个答案有什么问题?想详细说明您看到的问题吗?
      • 我个人没有否决您的回答,但无论哪种情况,它都没有具体解决我的问题。
      • 我不是在问如何实现权限系统,我是在询问有关基于现有方法生成动态权限列表的建议。
      • 这些函数将放在你的控制器类中。他们基于每个角色定义允许的操作。如果您想要一个特定控制器的权限,请检查 accessRules()。如果您想要控制器的所有操作,请检查它是否实现了基类,并合并 accessRules() 数组。也许我仍然以某种方式误解。祝你好运。
      • -1:您的建议基本上违反了OCP。查找控制器的职责是什么(例如在维基百科中,而不是在某些蹩脚框架的文档中)。控制器负责处理用户访问管理。
      猜你喜欢
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      • 2021-10-21
      • 2014-03-15
      • 1970-01-01
      • 1970-01-01
      • 2012-06-07
      • 2014-01-21
      相关资源
      最近更新 更多