Zend_Acl规则基于MVC和Propel模型

时间:2012-07-29 14:58:23

标签: php zend-framework zend-acl

我正在开展一个网络项目,其中一些访问决策取决于页面本身(例如/logout,只有登录用户才能看到)并且有些依赖于动态模型对象(例如/article/delete/1234我们必须检查登录用户是否写了1234,或者他是否是管理员。)

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

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

使用模块化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

1 个答案:

答案 0 :(得分:0)

我这样做的方式,自定义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

}

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