Zend_Acl基于MVC和Propel模型的规则



我有一个Web项目,其中某些访问决策取决于页面本身(例如 /logout仅对登录用户可见(,有些依赖于动态模型对象(例如 /article/delete/1234我们必须检查1234是由登录用户编写的还是他是否是管理员(。

现在,我面临的问题是如何将这两件事结合在一起。无论我如何尝试,我都不能单独依靠两者中的任何一个:

  • 有些页面不使用任何模型,所以我无法在那里设置任何模型规则
  • 另一方面,我无法为模块化方法创建动态断言,因为Comment只是一个comment而不是default/commentComment不限于默认模块,也可以在管理模块中使用。

使用模块化ACL,我正在尝试检查每个页面是否允许用户访问它,例如

if (!$acl->isAllowed($user, 'default/secrets', 'mysecrets')) {
    $this->forward('auth', 'login');
    $this->setDispatched(false);
}

通过动态断言,我正在检查是否允许某人编辑特定的模型对象。

// $comment has a method getResourceId() returning 'comment'
if ($acl->isAllowed($user, $comment, 'delete')) {
    // display a link for deletion
}

当然,如果检查

  • 删除特定评论,以及
  • 访问/comment/delete/???? 页面

会是一样的,但我想这是不可能的,我必须创建两个规则:

$acl->allow('member', 'default/comment', 'delete');
$acl->allow('member', 'comment', 'delete', new Acl_Assert_CommentAuthor());
$acl->allow('admin', 'comment', 'delete');

现在,这对我来说似乎并不完美,因为在某些情况下这可能会导致重复工作。

有没有更好的方法来解决这个问题?或者是唯一至少创建连贯命名方案的方法,例如:mvc:default/commentmodel:comment

我这样做的方式,限制结果的自定义sql查询,在插入/删除/修改sql之前检查的函数

然后是我写的一个 ACL 插件,它检查权限并使用这 5 个表

acl_groups
acl_permession
acl_permession_groups
acl_permession_risource
acl_risource

法典:

class Abc_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{
    /**
     * Return whether a given request (module-controller-action) exists
     *
     * @param Zend_Controller_Request_Abstract $request Request to check
     * @return boolean Whether the action exists
     */
    private function _actionExists(Zend_Controller_Request_Abstract $request)
    {
        $dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();
        // Check controller
        if (!$dispatcher->isDispatchable($request)) {
            return false;
        }
        $class  = $dispatcher->loadClass($dispatcher->getControllerClass($request));
        $method = $dispatcher->formatActionName($request->getActionName());
        return is_callable(array($class, $method));
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        // fetch the current user
        $controller = $request->controller;
        $action = $request->action;
        $logger = Zend_Registry::get('log');

        //prima controlla se sei autenticato e poi controlla se l'azione esiste, cosi non esponi il sito
        $auth = Zend_Auth::getInstance(); /* @var $auth Zend_Auth */
            if($auth->hasIdentity()) {

                if(! $this->_actionExists($request))//l'azione non esiste?
                {
                    $request->setControllerName('error');
                    $request->setActionName('pagenotfound');
                        $logger->notice( " IP: ". $_SERVER['REMOTE_ADDR']. " http://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]. " ?" .http_build_query($_REQUEST));
                    return ;
                }
                $allowed = Abc_Action_Helper_CheckPermission::checkPermission($controller, $action);
                if ($allowed !== 1)
                {
                    $request->setControllerName('error');
                    $request->setActionName('noauth');
                }
                //fine azione esiste
            }else{
                                    $request->setControllerName('user');
                $request->setActionName('login');
                return ;
            }

    }//fine preDispatch
}

然后,您可以添加您的代码(为了简短起见,我省略了它(以记住请求并在登录后将您重定向到那里。

最新更新