访问控制和XHR请求

时间:2013-05-09 13:39:43

标签: php ajax xmlhttprequest authorization acl

我正在为自定义框架的访问控制实施而苦苦挣扎。

不需要RBAC粒度,因此我决定采用某种资源的ACL 控制器动作。

这是数据库结构:

用户:

  • 约翰
  • 玛丽
  • 格雷格

user_groups:

  • 管理员
  • 会计师
  • 管理者

users_to_user_groups:

  • John =>管理员
  • Mary =>会计师
  • Greg =>管理者

资源(控制器操作):

  • 用户/编辑
  • 发票/添加
  • 客户/删除

resources_to_user_groups:

  • users / edit =>管理员
  • 发票/添加=>会计师
  • customers / delete =>管理者

这是[伪]代码。

$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请求 加载订单位置和其他数据等。

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

  • 发票清单(发票/清单,发票/ xhr_get_total_amount)
  • 订单清单(订单/清单,订单/ xhr_get_positons_for_order,订单/ xhr_get_some_other_data)
  • 添加新用户(users / new)#单一操作,新用户输入表单不使用XHR请求

...而不是将资源分配给用户组,而是将资源组分配给用户组。

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

4 个答案:

答案 0 :(得分:2)

为什么不将新列添加到名为resources的{​​{1}}表中,该表将存储依赖xhr资源的数组?所以它看起来像:

descendants

此外,如果尚未实现:您可以在请求开始时获取并处理允许资源及其后代的整个列表到单个数组,并将它们存储到响应。因此,每次需要检查访问权限时,您都不会询问数据库。

答案 1 :(得分:2)

过去一年我一直在处理同样的问题,而这就是我如何处理它。

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

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

以下是如何操作的示例:

  1. 构造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);
    
  2. 定义资源分组:

    $resources = array(
        'group 1' => array(
            'resource 1'
            , 'resource 2'
            , 'resource 3'
        )
        , 'group 2' => array(
            'resource 1'
            , 'resource 4'
            , 'resource 5'
        )
    );
    
  3. 将您的资源引入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');
    
  4. 使用ACL的引擎查询权限:

    echo $acl->isAllowed('someUser', 'resource 1') ? 'allowed' : 'denied';
    
  5. 如你所见,我在这里没有做任何特别的事。这里介绍的唯一新概念是添加到ACL引擎的资源与用于查询它的资源不同。但是在我们实际调用ZF的库之前已经完成了一层,因此查询ZF的ACL的调用仍然有效。

    我希望我能清楚地写下我的观点。不要忘记我只是想给你一个概念,你需要自己想出实际的实现。

答案 2 :(得分:1)

我知道我并没有直接回答你的问题,但也许我可以向你发送一条稍微不同的路径,一旦你的网站规模和复杂性增加,这将更加灵活。在我阅读this帖后,我已将我的身份验证系统切换为基于活动(允许活动“doSomething”),远离基于角色(“管理员”可以执行以下操作....)。

只是一个想法。

答案 3 :(得分:1)

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

if ($ref_url)
  header("Access-Control-Allow-Origin:"+$ref_url);
else
  header("Access-Control-Allow-Origin:*");