Zend Navigation: Где я должен загрузить ACL 'Role' в частном приложении?
Я работаю над "частным" приложением, вы должны войти в систему, чтобы сделать что-либо вообще. Это дает мне небольшую проблему при загрузке роли для Zend Navigation. В настоящее время я запускаю Zend Navigation в моей начальной загрузке; это было нормально, пока я не добавил ACL в Zend Nav. Проблема в том, что я хочу загрузить 'userRole' из моего хранилища аутентификации, но пока пользователь не войдет в систему, пока не будет хранилища, поэтому я получаю предупреждение "Попытка получить свойство не-объекта" на странице входа в систему., Это потому, что перед входом в систему ничего нет в хранилище аутентификации, поэтому auth->userRole
"ничего", потому что auth->getInstance()->getIdentity()->???
будет пустым, пока пользователь не войдет в систему и не настроит аутентификацию.
Я не использую Zend Nav на странице входа в систему, на самом деле у меня есть альтернативный макет для страницы входа (вообще никакой навигации); 'if !$auth->hasIdentity'
(false) использовать макет входа в систему, отображать только страницу входа для всей системы, как я уже говорил, приложение полностью закрытое, поэтому использование по умолчанию роли "гость" или что-то подобное выглядит как "грязный" подход, потому что однажды пользователь вошел в систему, так или иначе, придется перенастроить аутентификацию. Кажется неправильным устанавливать общую идентификационную информацию только для того, чтобы угодить странице входа.
Я имею в виду, где хорошее место для перемещения 'init' Zend Nav или, по крайней мере, для перемещения части конфигурации ACL? Можно ли сдвинуть все это?
Это то, что у меня есть в моем bootstrap.php для Zend Navigation:
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 происходят либо в контроллере (в действии), либо некоторые могут происходить в моделях в какой-то момент, хотя я не ожидаю веб-службы или чего-то еще, поэтому, возможно, они останутся в контроллере, но я имею гибкость, потому что у меня есть ACL в моделях (это было бы "доменом" правильно?
Я использую ACL на Zend Nav только для разметки, для удобства пользователей; Меню и ссылки, которые я получаю из Zend Nav, будут "серыми", несуществующими или активными (и видимыми) в зависимости от роли пользователя, например, роль "пользователь" не будет иметь много опций "администратор", и это усилен ACL в контроллере, так что нельзя просто набрать url и попасть в область.
Моя другая мысль заключалась в том, что, возможно, мне стоит подумать о переносе своего логина в загрузчик для этой ситуации, но я не уверен, что это тоже хорошая идея?
РЕДАКТИРОВАТЬ: Это код, который я вставил в плагин Front Controller:
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);
}
}
}
Работает отлично; Я, конечно, должен был зарегистрировать свой плагин, как и любой другой. Я также перенес свою проверку аутентификации на плагин фронт-контроллера.
2 ответа
Вы можете создать анонимную роль перед входом в систему и обработать очень короткую политику ACL для анонимных пользователей. Проверьте этот ответ, например, о том, как поймать неавторизованных пользователей в PreDispatch с плагином Auth.
Я бы не вытащил его прямо из хранилища Auth. Если вы извлекаете его из Zend_Auth и во время этого сеанса пользователя изменяется роль пользователя, вам придется либо принудительно выйти из системы / войти в систему, либо обновить информацию в хранилище Zend_Auth. Мне проще настроить класс Role и выполнить логику, чтобы определить роль там или установить роль по умолчанию (guest). Класс роли 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;
}
}