1

我有一个 web 项目,其中一些访问决策取决于页面本身(例如/logout,它应该只对登录用户可见),有些取决于动态模型对象(例如/article/delete/1234,我们必须检查是否1234由登录用户编写用户或者如果他是管理员)。

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

  • 有些页面不使用任何模型,所以我不能在那里设置任何模型规则
  • 另一方面,我不能为模块化方法创建动态断言,因为它只是 a而不是 a 。A不限于默认模块,也可以在管理模块中使用。Commentcommentdefault/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

4

1 回答 1

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

}

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

于 2012-07-30T09:30:09.670 回答