【问题标题】:Access Control Problem访问控制问题
【发布时间】:2011-06-12 17:11:10
【问题描述】:

我正在为我的项目开发一个访问控制库,我正在寻找最好的解决方案:

我正在将我的所有访问列表从数据库获取到一个数组。结果看起来像这样:

$array = array(
    '*' => array('administrator' => TRUE),
    'frontend/*' => array(
        'user' => TRUE,
        'unregistered' => TRUE
        ),
    'backend/*' => array(
        'user' => FALSE,
        'unregistered' => FALSE
    ),
    'backend/user/*' => array(
        'moderator' => FALSE,
        'supermoderator' => TRUE,
    ),
    'backend/article/*' => array(
        'supermoderator' => TRUE
    ),
    'backend/article/add/new' => array(
        'moderator' => TRUE
    )
);

“ * ”表示该用户可以访问所有相关选项 backend/article/* 表示该组可以访问所有文章选项(文章/添加、文章/删除...)。

如您所见,backend/article/add 中没有超级版主的项目,但它拥有对所有文章页面的主访问权限。

检查这个的最好方法是什么?我试过array_walk(),但我想它对我没有帮助。

感谢您的建议...

如果你愿意,我可以分享我的整个代码。

* 编辑 *

我存储错了吗?如果您有更好的解决方案来存储它,我会很高兴听到它。

感谢您的建议

【问题讨论】:

    标签: php arrays multidimensional-array access-control


    【解决方案1】:

    无论这将是一个复杂的算法,简单的array_walk 都不会。除非有人觉得特别慷慨并会为你写一个,否则我建议你聘请一名程序员。


    我存储错了吗?如果您有更好的解决方案来存储它,我会很高兴听到它。

    这完全取决于您的算法。您可能可以编写一个使用您当前数据格式的文件。如果你改变你的数据格式,你也可以写一个更简单的。但是你的数据格式应该是什么样子,嗯,这是程序员的工作。

    【讨论】:

    • 是的,我可以通过分解资源并检查它来做到这一点。我不需要程序员。但是由于我不是很了解所有的 php 函数,所以我认为一些编码人员可以建议我使用函数。
    • 除了foreachexplodein_array 之外,您并不特别需要任何 PHP 函数,但这些函数在任何语言中都很常见,因此您的论点完全没有意义。你需要一个算法。
    • 如何存储它们?我正在使用资源 => 组关系。组=>资源关系会不会更有帮助?
    【解决方案2】:

    我自己找到了答案:

    假设用户试图访问backend/article/add/new 和超级版主组中的这个用户。所以我需要寻找backend/*backend/article/*backend/article/add/*array_slice()for() 足够了:

    顺便说一句,我正在使用 CodeIgniter。我对其进行了一些修改以分离前端和后端控制器。我没有使用application/controller 目录。我正在为控制器使用application/backendapplication/frontend 目录。

    所以一个 uri 模式是这样的:http://site.com/[backend]*/[directory]*/class/method

    // This is the page that user trying to reach
    $requested_page = "backend/article/add/new";
    
    // pharsing...
    $x = explode('/', $requested_page);
    
    // this is needed to cut last 3, 2, 1 items of $x
    $i = count($x) > 3 ? -4 : -count($x);
    
    for (; $i < 0; $i++) {
        $resource = implode('/', array_slice($x, 0, $i)) . '/*';
        // echoing for debug
        echo $resource;
    }
    
    // Outputs:
    // backend/*
    // backend/article/*
    // backend/article/add/*
    

    【讨论】:

      【解决方案3】:
      function userHasPermissions($permissionsArray, $user, $path) {
          // Check exact
          if(isset($permissionsArray[$path]) &&
             isset($permissionsArray[$path][$user])) {
              return $permissionsArray[$path][$user];
          }
      
          // Check lower and lower
          $partArr = explode('/', $path);
          for($i = substr_count($path, '/'); $i >= 0; $i--) {
              if($i > 0) {
                  $choppedPartArr = array_slice($partArr, 0, $i);
                  $newPath = implode($choppedPartArr, '/') . '/*';
              } else {
                  $newPath = '*';
              }
      
              if(isset($permissionsArray[$newPath]) &&
                 isset($permissionsArray[$newPath][$user])) {
                  return $permissionsArray[$newPath][$user];
              }
          }
      
          return false;
      }
      
      echo "Result: " . (userHasPermissions($array, 'supermoderator', 'backend/article/add') ? "true" : "false");
      

      请注意,“超级版主”的“后端/文章”将返回 false,因为“后端/文章/*”与它不匹配。要更改此设置,只需将 $i = substr_count($path, '/'); 更改为 $i = substr_count($path, '/')+1;

      【讨论】:

        猜你喜欢
        • 2013-10-20
        • 2016-06-02
        • 2020-10-16
        • 2013-11-15
        • 1970-01-01
        • 2023-04-01
        • 2017-07-06
        相关资源
        最近更新 更多