PHP应用程序中的访问控制体系结构

时间:2012-02-09 19:13:50

标签: php model-view-controller acl

我正在试图弄清楚如何限制我目前正在处理的PHP项目中对特定资源的访问。我已经找到了现有的解决方案,但它们都不符合我的需求(例如,Zend_Acl)。

现在我想出了类似的东西:(当然,这非常,非常简化。没有例外或其他什么。足以说明问题)

class Access {
    protected $_context;
    protected $_handlers;
    public function __construct($context) {
        $this->_context = $context;
    }
    public static function registerHandler(Access_Handler $handler) {
        $key = $handler->getContextType().'/'.$handler->getResourceType();
        self::$_handlers[$key] = $handler;
    }
    public function isAllowed($resource) {
        return $this->getHandler($resource)->isAllowed($this->_context, $resource);
    }
    public function getHandler($resource) {
        // Look for and return the appropriate handler for the combination of 
        // $context and $resource
    }
}

abstract class Access_Handler {
    $_contextType;
    $_resourceType;
    abstract public function isAllowed();
}

class Access_Handler_UserInvoice extends Access_Handler {
    $_contextType = 'User';
    $_resourceType = 'Invoice';
    public function isAllowed($user, $invoice) {
        if($invoice->user_id === $user->id) {
            return true;
        }
        return false;
    }
}

然后我会在我的Application Bootstrap中执行类似的操作:

protected function $_initAccessHandlers() {
    Access::registerHandler(new Access_Handler_UserInvoice());
}

在我的控制器中(因为I've heard你应该放置你的访问控制)我会有这样的事情:

class InvoiceController {
    public function viewAction() {
        // $this->me is of type User
        $access = new Access($this->me);
        if($access->isAllowed($this->invoice)) {
            // ...
        }
    }
}

我没有测试过代码,所以可能会出现拼写错误或其他错误,但我认为你得到了主旨。另外,实际上我可能会将Access实现为Singleton或Multiton,但这不是我的问题所在。

这是正确的方法吗?这对我来说似乎很自然,但后来我想知道为什么没有其他人这样做。

我的开发堆栈是PHP / MySQL / Zend Framework / Doctrine。

1 个答案:

答案 0 :(得分:1)

使用Zend_Acl,您将执行基本控制,例如:

$acl = new Zend_Acl();
$acl->add(new Zend_Acl_Resource('article'));
$acl->addRole(new Zend_Acl_Role('author'));
$acl->deny();
$acl->allow('author', 'article', array('list'));

然后你可以使用断言做你想做的事情:

$user = Zend_Auth::getInstance()->getIdentity();
$assertion = new My_Acl_Assertion_ArticleEditCheck($user);
$acl->allow('author', 'article', 'edit', $assertion);

您可以代替将用户对象传递给断言,将其实现为内部属性,并在必要时处理请求参数。

参考文献:

http://framework.zend.com/manual/en/zend.acl.advanced.html

Dynamic custom ACL in zend framework?

有关断言的更高级用法,请查看:

http://www.aviblock.com/blog/2009/03/19/acl-in-zend-framework/

http://ralphschindler.com/2009/08/13/dynamic-assertions-for-zend_acl-in-zf