3

我正在开发一个“私人”应用程序,您必须登录才能执行任何操作。这让我在为 Zend Navigation 加载角色时遇到了一些问题。目前,我正在引导程序中“初始化 Zend Navigation”;这很好,直到我将 ACL 添加到 Zend Nav。问题是我想从我的身份验证存储中加载“userRole”,但在用户登录之前不会有存储,所以在登录页面上会出现“尝试获取非对象的属性”警告. 这是因为在登录之前,auth 的存储中没有任何内容,auth->userRole“nothing”也是如此,因为auth->getInstance()->getIdentity()->???它将是空的,直到用户登录并配置了 auth。

我没有在登录页面使用 Zend Nav,事实上我有一个用于登录页面的替代布局(根本没有导航);'if !$auth->hasIdentity'(false) 使用登录布局,只在系统范围内显示登录页面,正如我所说的应用程序是完全私有的,所以默认为“访客”角色或类似的东西似乎是一种“肮脏”的方法,因为一旦无论如何,用户登录它都必须重新配置身份验证。只是为了取悦登录页面而设置通用身份验证身份似乎并不正确。

我得到的是,哪里是移动 Zend Nav 的“init”的好地方,或者至少移动配置 ACL 部分?也可以移动整个东西?

这就是我在 Zend Navigation 的 bootstrap.php 中的内容:

protected function _initNavigation() {
    $this->_logger->info('Bootstrap ' . __METHOD__);

    $this->bootstrap('layout');
    $layout = $this->getResource('layout');
    $view = $layout->getView();
    $config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
    $container = new Zend_Navigation($config);
    $acl = new Application_Model_Acl_Acl();
    $role = Zend_Auth::getInstance()->getIdentity()->userRole;
    $view->navigation($container)->setAcl($acl)->setRole($role);
}

在引导程序运行时它'$role = Zend_Auth::getInstance()->getIdentity()->userRole'是空的(或非对象)。

我所有的 ACL 都发生在控制器中(在动作中),或者有些可能在某个时候发生在模型中,尽管我不期待 Web 服务或任何东西,所以也许它们会留在控制器中,但我有灵活性,因为我在模型中有 ACL(那将是“域”对吗?

我只在 Zend Nav 上使用 ACL 来进行布局、用户体验;根据用户角色,我从 Zend Nav 获得的菜单和链接将显示为“灰色”、不存在或活动(且可见),例如,“用户”角色不会获得很多“管理员”选项,这是由控制器中的 ACL 重新实施,因此人们也不能简单地输入 url 并进入一个区域。

我的另一个想法是,也许我应该考虑将我的登录名转移到这种情况下的引导程序中,但我也不确定这是否是个好主意?


编辑: 这是我放入前端控制器插件的代码:

class Plugins_Controller_ZendNavInit extends Zend_Controller_Plugin_Abstract {

        public function preDispatch(Zend_Controller_Request_Abstract $request) {

            $auth = Zend_Auth::getInstance();

            if ($auth->hasIdentity()) {

                $config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
                $container = new Zend_Navigation($config);
                $acl = new Application_Model_Acl_Acl();

                $layout = Zend_Layout::getMvcInstance();
                $view = $layout->getView();

                $role = Zend_Auth::getInstance()->getIdentity()->userRole;
                $view->navigation($container)->setAcl($acl)->setRole($role);
            }
        }
    }

效果很好;当然,我必须像其他任何插件一样注册我的插件。我也将我的 Auth 检查移至前端控制器插件。

4

2 回答 2

3

您可以在登录之前建立一个匿名角色,并为匿名用户处理一个非常短的 ACL 策略。检查此响应,例如如何使用 Auth Plugin 在 PreDispatch 上捕获未经身​​份验证的用户。

于 2011-04-29T08:14:54.583 回答
1

我不会直接从 Auth 存储中提取它。如果您从 Zend_Auth 中提取它并且在该用户会话期间用户的角色被更改,您将不得不强制注销/登录或更新 Zend_Auth 存储中的信息。我发现设置 Role 类并执行逻辑来确定角色或设置默认(来宾)角色更容易。User 角色类扩展了我的 User 模型并实现了 Zend_Acl_Role_Interface。然后我可以从 Role 类中查询数据库。我大约一天前开始实施这个,但这里有一个例子:

<?php

类 Zfcms_Acl_Role_User 扩展 Zfcms_Model_Users 实现 Zend_Acl_Role_Interface {

/**
 * Unique id of Role
 *
 * @var string
 */
protected $_roleId;
public $_inheritsFrom = 'guest';
public $_defaultRole = 'user';

/**
 * Sets the Role identifier
 *
 * @param  string $id
 * @return void
 * Defined by Zend_Acl_Role_Interface; returns the Role identifier
 *
 * @return string
 */
public function getRoleId()
{
    //$auth = Zend_Auth::getInstance();
    if(Zend_Auth::getInstance()->hasIdentity()) 
    {
        $this->_roleId = self::getUserRoleById(Zend_Auth::getInstance()->getIdentity()->user_id);
        return $this->_roleId;
    } 
    elseif(!Zend_Auth::getInstance()->hasIdentity() && !isset($this->role))
    {
        //return 'guest';
        return (string) new Zfcms_Acl_Role_Guest();
    } else {
        throw new Zend_Controller_Action_Exception('Invalid user roleId', 110);
    }
}
public function getDefaultRole()
{
    return $this->_defaultRole;
}
public function getPrivsByRole($role)
{
   //TODO: Design db table to hold privs
}
private function setPrivs()
{
   //TODO: implement
}
/**
 * Defined by Zend_Acl_Role_Interface; returns the Role identifier
 * Proxies to getRoleId()
 *
 * @return string
 */
public function __toString()
{
    return $this->getRoleId();
}
public function getUserRoleById($id)
{
    $this->_id = $id;
    $query = $this->select()
                  ->from('users', array('user_id', 'role'))
                  ->where('user_id = ?', $this->_id);

    $result = $this->fetchAll($query);
    foreach($result as $userRole)
    {
        $role = $userRole->role;
    }
    return $role;
}

}

于 2011-07-22T20:44:41.730 回答