Php 访问控制和XHR请求

Php 访问控制和XHR请求,php,ajax,xmlhttprequest,authorization,acl,Php,Ajax,Xmlhttprequest,Authorization,Acl,我正在努力实现自定义框架的访问控制 RBAC粒度是不需要的,所以我决定使用某种ACL来存储资源 控制器动作 以下是数据库结构: 用户: 约翰 玛丽 格雷格 用户组: 管理员 会计人员 管理者 用户到用户组: John=>管理员 玛丽=>会计师 格雷格=>经理 资源(控制器操作): 用户/编辑 发票/添加 客户/删除 资源到用户组: 用户/编辑=>Administrators 发票/添加=>会计师 客户/删除=>经理 这是[伪]代码 $user = new User; // T

我正在努力实现自定义框架的访问控制

RBAC粒度是不需要的,所以我决定使用某种ACL来存储资源 控制器动作

以下是数据库结构:

用户:

  • 约翰
  • 玛丽
  • 格雷格
用户组:

  • 管理员
  • 会计人员
  • 管理者
用户到用户组:

  • John=>管理员
  • 玛丽=>会计师
  • 格雷格=>经理
资源(控制器操作):

  • 用户/编辑
  • 发票/添加
  • 客户/删除
资源到用户组:

  • 用户/编辑=>Administrators
  • 发票/添加=>会计师
  • 客户/删除=>经理
这是[伪]代码

$user = new User; // This will be currently logged in user ...

$acl = new Acl($user);

$dispatcher = new Dispatcher($acl);

$dispatcher->dispatch('users', 'new');

class Dispatcher
{
    public function dispatch($controller, $action)
    {
        $permission = $controller . '/' . $action;

        if(!$this->acl->isAllowed($permission))
        {
            throw new AccessDeniedException("Access denied");
        }

        // User is authorized to execute this action, dispatch ...
    }
}
我喜欢这种方法。。。直到我意识到还有很多XHR请求

例如,发票列表使用XHR请求获取总金额,订单列表使用XHR请求 加载订单位置和其他数据等

因此,必须有一些资源分组,例如,新表资源组:

  • 发票清单(发票/清单、发票/xhr\U get\U总额)
  • 订单列表(订单/列表,订单/xhr\u获取订单的位置,订单/xhr\u获取一些其他数据)
  • 添加新用户(用户/新)#单个操作,新用户输入表单不使用XHR请求
。。。将资源组分配给用户组,而不是将资源分配给用户组


感觉很复杂。这是正确的方法吗?有什么可以改进的?有什么框架可以解决这个问题吗?

我知道我不是直接回答你的问题,但也许我可以给你一个稍微不同的路径,一旦你的网站规模和复杂性增加,这个路径将变得更加灵活。读了这篇文章后,我将身份验证系统切换到基于活动(允许活动“doSomething”),而不是基于角色(“管理员”可以执行以下操作……)


只是想一想。

最好不要使用*而使用请求文件的域。 *将在某些版本的IE中失败(不记得wich)


为什么不在
资源
表中添加一个新列,称为
子体
,它将存储一个依赖于xhr资源的数组?所以它可能看起来像:

resource: "invoices/list"
descendants: ["invoices/xhr_get_total_amount"]

resource: "orders/list"
descendants: ["orders/xhr_get_positons_for_order","orders/xhr_get_some_other_data"]

resource: "users/new"
descendants: []

另外,如果还没有实现:您可以在请求开始时将允许的资源及其子代的整个列表获取并处理到单个数组,并将其存储到响应。所以,您不会在每次需要检查某个access时都询问数据库。

在过去的一年中,我一直在处理相同的问题,下面是我如何解决的

首先,我使用library作为基本引擎来告诉我某个用户是否可以访问某些资源。由于ZF已经支持用户分组和角色(包括角色层次结构),您不必再担心这些

撇开用户分组和角色不谈,下一步是资源分组,ZF内部不支持(遗憾的是)。我相信这是你的问题所关注的部分。然而,您可以使用ZF并扩展它以满足您的需要。您所需要做的就是为资源(平面或层次)提出一种分组机制。然后,您可以按照其手册中的说明使用ZF

下面是一个关于如何做到这一点的示例:

  • 构造ACL引擎和其他基本对象:

    $acl = new Zend_Acl();
    
    $acl->addRole(new Zend_Acl_Role('guest'))
        ->addRole(new Zend_Acl_Role('member'))
        ->addRole(new Zend_Acl_Role('admin'));
    
    $parents = array('guest', 'member', 'admin');
    $acl->addRole(new Zend_Acl_Role('someUser'), $parents);
    
  • 定义您的资源分组:

    $resources = array(
        'group 1' => array(
            'resource 1'
            , 'resource 2'
            , 'resource 3'
        )
        , 'group 2' => array(
            'resource 1'
            , 'resource 4'
            , 'resource 5'
        )
    );
    
  • 向ACL引擎介绍您的资源:

    function addResource(Zend_Acl $acl, $resources, $groupName)
    {
        foreach ($resources[$groupName] as $resource) {
            $acl->add(new Zend_Acl_Resource($resource));
        }
    }
    
    addResource($acl, $resources, 'group 2');
    
  • 使用ACL引擎查询权限:

    echo $acl->isAllowed('someUser', 'resource 1') ? 'allowed' : 'denied';
    
  • 正如你所看到的,我在这里没有做什么特别的事。这里引入的唯一新概念是,添加到ACL引擎的资源与用于查询它的资源不同。但在我们实际调用ZF的库之前,它是在一层完成的,所以查询ZF的ACL的调用仍然有效


    我希望我能把我的观点写清楚。别忘了,我只是想给您一个概念,您需要自己提出实际的实现。

    为什么XHR很重要?具有相同权限的同一用户以相同的方式访问相同的资源,它只是以不同的方式打包并交付给客户端。如果不止这些,那么这里就没有足够的信息能够为您提供任何有意义的帮助。Jason-因为单个“资源”(Dudenrock提到的更好的措辞是“活动”)可以由单个静态HTTP请求组成,或者另外调用一个或多个XHR请求。所以,我们不能假设每个controller::action对都是“permission”,我们需要以某种方式对它们进行分组。如果您是基于“请求”创建权限的(或者,尽可能地说,每个URL都有自己的特定权限),那么您将走上一条无法维护的道路。创建组来添加这些请求,只是稍微抽象一下维护问题。现在,您不会是第一个采用这种方法的人(我工作中使用的遗留系统,最初基于osCommerce,控制每个文件名的访问),但是如果您的应用程序现在或者希望达到任何中等大小,您会感到头疼。是的,您对我的初始计划是正确的,每个控制器::操作对(或URL)需要单独的许可。但正如我在文章末尾提到的,我认为有必要将一些操作组合在一起,形成一个权限/活动。你建议的方法是什么?我给你一个例子——活动“查看日志”,它由两个控制器动作组成——一个静态HTTP请求,它绘制一些表格HTML标记,在这个页面中还有一个XHR请求,它获取最新的日志记录,比如说,每30秒一次。如何在单个权限下合并这些功能?@LaurisB:XHR请求可以调用表示receivi中活动的几个不同函数
    echo $acl->isAllowed('someUser', 'resource 1') ? 'allowed' : 'denied';