В настоящее время я работаю над сайтом, который требует ACL, и поскольку я использую Zend, для меня имеет смысл использовать свой класс ACL, но у меня мало что необходимо для того, чтобы сделать это. Я прочитал документы, но это еще больше смутило меня … в основном все, что я хочу сделать, это настроить две группы пользователей, например, «нормальный» и «админ», обычные пользователи могут получить доступ ко всем страницам, на которых есть контроллер, который не является администратором, а Администратор может явно получить доступ к страницам контроллера администратора.
У меня много вопросов:
Я был бы очень признателен, если бы вы направили меня на сайт или хороший учебник.
Я реализовал подобную вещь не так давно. Базовая концепция следует в примере кода.
Я создал свой собственный файл configAcl.php, который загружается в файл начальной загрузки, в моем случае это index.php. Вот как это будет по вашему делу:
$acl = new Zend_Acl(); $roles = array('admin', 'normal'); // Controller script names. You have to add all of them if credential check // is global to your application. $controllers = array('auth', 'index', 'news', 'admin'); foreach ($roles as $role) { $acl->addRole(new Zend_Acl_Role($role)); } foreach ($controllers as $controller) { $acl->add(new Zend_Acl_Resource($controller)); } // Here comes credential definiton for admin user. $acl->allow('admin'); // Has access to everything. // Here comes credential definition for normal user. $acl->allow('normal'); // Has access to everything... $acl->deny('normal', 'admin'); // ... except the admin controller. // Finally I store whole ACL definition to registry for use // in AuthPlugin plugin. $registry = Zend_Registry::getInstance(); $registry->set('acl', $acl);
Другим случаем является то, что вы хотите разрешить нормальное пользовательское действие только «список» на всех ваших контроллерах. Это довольно просто, вы должны добавить строку следующим образом:
$acl->allow('normal', null, 'list'); // Has access to all controller list actions.
Затем вы должны создать новый плагин, который автоматически проверяет учетные данные, когда есть запрос на какое-либо действие контроллера. Эта проверка выполняется в методе preDispatch (), который вызывается перед каждым вызовом действия контроллера.
Вот AuthPlugin.php:
class AuthPlugin extends Zend_Controller_Plugin_Abstract { public function preDispatch(Zend_Controller_Request_Abstract $request) { $loginController = 'auth'; $loginAction = 'login'; $auth = Zend_Auth::getInstance(); // If user is not logged in and is not requesting login page // - redirect to login page. if (!$auth->hasIdentity() && $request->getControllerName() != $loginController && $request->getActionName() != $loginAction) { $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector'); $redirector->gotoSimpleAndExit($loginAction, $loginController); } // User is logged in or on login page. if ($auth->hasIdentity()) { // Is logged in // Let's check the credential $registry = Zend_Registry::getInstance(); $acl = $registry->get('acl'); $identity = $auth->getIdentity(); // role is a column in the user table (database) $isAllowed = $acl->isAllowed($identity->role, $request->getControllerName(), $request->getActionName()); if (!$isAllowed) { $redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector'); $redirector->gotoUrlAndExit('/'); } } } }
Завершающие шаги загружают ваш configAcl.php и регистрируют AuthPlugin в файле начальной загрузки (возможно, index.php).
require_once '../application/configAcl.php'; $frontController = Zend_Controller_Front::getInstance(); $frontController->registerPlugin(new AuthPlugin());
Итак, это основная концепция. Я не тестировал вышеприведенный код (копировать и вставлять и переписывать только для цели витрины), чтобы он не был пуленепробиваемым. Просто чтобы дать представление.
РЕДАКТИРОВАТЬ
Для ясности. В приведенном выше коде AuthPlugin предполагается, что объект $ identity заполнен данными пользователя (столбец «role» в базе данных). Это можно сделать в процессе входа в систему следующим образом:
[...] $authAdapter = new Zend_Auth_Adapter_DbTable($db); $authAdapter->setTableName('Users'); $authAdapter->setIdentityColumn('username'); $authAdapter->setCredentialColumn('password'); $authAdapter->setIdentity($username); $authAdapter->setCredential(sha1($password)); $authAdapter->setCredentialTreatment('? AND active = 1'); $auth = Zend_Auth::getInstance(); $result = $auth->authenticate($authAdapter); if ($result->isValid()) { $data = $authAdapter->getResultRowObject(null, 'password'); // without password $auth->getStorage()->write($data); [...]
Это решение может оказаться простейшей реализацией Zend_Acl.
Пример:
class UserController extends Zend_Controller_Action { public function preDispatch(){ $resource = 'user_area'; $privilege = $this->_request->getActionName(); if (!$this->_helper->acl($resource, $privilege)) $this->_redirect(); } }
Zend / Controller / Action / Helper / Acl.php
class Zend_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract { protected $acl; protected $role; protected function getAcl(){ if (is_null($this->acl)){ $acl = new Zend_Acl(); $acl->addResource(new Zend_Acl_Resource('user_area')); $acl->addResource(new Zend_Acl_Resource('customer_area'), 'user_area'); $acl->addResource(new Zend_Acl_Resource('web_area')); $acl->addRole(new Zend_Acl_Role('guest')); $acl->addRole(new Zend_Acl_Role('user'), 'guest'); $acl->allow('guest', 'web_area'); $acl->allow('guest', 'user_area', array( 'forgot-password', 'login' )); $acl->allow('user', 'user_area'); $acl->allow('customer', 'customer_area'); $this->acl = $acl; } return $this->acl; } protected function getRole(){ if (is_null($this->role)){ $session = new Zend_Session_Namespace('session'); $role = (isset($session->userType)) ? $session->userType : 'guest'; $this->role = $role; } return $this->role; } public function direct($resource, $privilege = null){ $acl = $this->getAcl(); $role = $this->getRole(); $allowed = $acl->isAllowed($role, $resource, $privilege); return $allowed; } }
Играйте с этой структурой. получить роль и ресурсы из базы данных и сохранить это в сеансе или для любого кэширования.