Использование Zend_Auth для защиты всех контроллеров

Как бы я глобально защитил все мои контроллеры (кроме моего контроллера входа), чтобы обеспечить мое приложение безопасным во всех точках (без скрытого бэкдора на вызовы ajax и т. Д.). Я думал, что могу поместить его в свой файл начальной загрузки, но это не так? Я пытаюсь не добавлять код к каждому контроллеру.

Предложения?

edit : это дополнение к ответу @singles.

Вы должны понимать, что есть две разные вещи. Auth и Acl . Auth сообщает вам, кто является пользователем, и вы можете, например, перенаправить пользователя, не имеющего Auth, в контроллер входа в систему и установить идентификатор авторизации после входа в систему. то система Acl принимает решения «да / нет» на основе данных Auth (может быть идентификатором пользователя или является ролью, хранящейся в хранилище Auth.

В хорошем решении нужно иметь 2 плагины контроллеров (зарегистрированных в хорошем порядке в бутстрапе, Auth then Acl). Если вы не используете плагины контроллера, вам нужно будет вызвать проверку Acl в каждом контроллере, когда это необходимо. Если вам это всегда нужно, используйте плагины.

Внедрите preDispatch() в плагин Auth, чтобы установить, например, анонимную идентификацию, если у вас нет возврата идентификатора из Zend_Auth. Это фрагмент кода реального:

 public function preDispatch(Zend_Controller_Request_Abstract $request) { $module = $request->getModuleName(); $controller = $request->getControllerName(); $action = $request->getActionName(); $auth = Zend_Auth::getInstance(); if (!$auth->hasIdentity()) { // set a default anonymous identity $auth->getStorage()->write(array('name' => 'anonymous','role' => 1,)); } (...) 

А для плагина контроллера Acl задача также находится в preDispatch() . Вы можете запустить проверку acl для каждого запрошенного URL-адреса (так что для каждого пользовательского запроса, даже ajax). Вот частичный фрагмент, так что это просто пример того, как вы могли бы обрабатывать вещи:

 public function preDispatch(Zend_Controller_Request_Abstract $request) { $controller = $request->controller; $module = $request->module; $action = $request->action; // here you should code something nice retrieving you Zend_Acl object // with some caching options maybe, building roles, ressources, etc $this->_acl = $this->getAcl(); if (!$this->_acl->isCurrentUserAllowed($module,'see')) { $auth = Zend_Auth::getInstance(); $identity = $auth->hasIdentity('identity')? $auth->getIdentity() : null; if(isset($identity)) { if($identity['name'] == 'anonymous') { // WARNING: avoid infinite redirect loops on login page if (!($request->getControllerName() == 'login' && $request->getActionName()=='login' && $request->getModuleName() == 'default')) { $request->setControllerName('login') ->setActionName('login') ->setModuleName('default'); return; (...) в public function preDispatch(Zend_Controller_Request_Abstract $request) { $controller = $request->controller; $module = $request->module; $action = $request->action; // here you should code something nice retrieving you Zend_Acl object // with some caching options maybe, building roles, ressources, etc $this->_acl = $this->getAcl(); if (!$this->_acl->isCurrentUserAllowed($module,'see')) { $auth = Zend_Auth::getInstance(); $identity = $auth->hasIdentity('identity')? $auth->getIdentity() : null; if(isset($identity)) { if($identity['name'] == 'anonymous') { // WARNING: avoid infinite redirect loops on login page if (!($request->getControllerName() == 'login' && $request->getActionName()=='login' && $request->getModuleName() == 'default')) { $request->setControllerName('login') ->setActionName('login') ->setModuleName('default'); return; (...) по public function preDispatch(Zend_Controller_Request_Abstract $request) { $controller = $request->controller; $module = $request->module; $action = $request->action; // here you should code something nice retrieving you Zend_Acl object // with some caching options maybe, building roles, ressources, etc $this->_acl = $this->getAcl(); if (!$this->_acl->isCurrentUserAllowed($module,'see')) { $auth = Zend_Auth::getInstance(); $identity = $auth->hasIdentity('identity')? $auth->getIdentity() : null; if(isset($identity)) { if($identity['name'] == 'anonymous') { // WARNING: avoid infinite redirect loops on login page if (!($request->getControllerName() == 'login' && $request->getActionName()=='login' && $request->getModuleName() == 'default')) { $request->setControllerName('login') ->setActionName('login') ->setModuleName('default'); return; (...) 

и в этой системе последней важной частью является LoginController, где в случае успешного входа в систему вы должны запустить идентификационную запись:

 (...) $auth = Zend_Auth::getInstance(); Zend_Session::regenerateId(); $storage = $auth->getStorage(); $rowobject = $authAdapter->getResultRowObject(null,'passwd'); $storage->write((array)$rowobject); (...) 

Вы должны написать плагин ACL для этого и зарегистрировать его на переднем контроллере. Если вы реализуете такую ​​функциональность, как плагин, вы будете иметь гибкость, чтобы использовать ее в своем следующем приложении – без необходимости расширения каждого контроллера с вашего настраиваемого контроллера.

Ресурсы:
1. Плагины переднего контроллера в Zend Framework – как работают плагины в ZF
2. Пример сценария Zend_Acl / Zend_Auth – одна из многих возможных реализаций плагина ACL.
3. Google – и много других ресурсов

Ну, у вас должна быть точка входа в вашу систему 🙂

Это может быть достигнуто путем расширения Zend_Controller_Action, скажем:

 abstract class MyController extends Zend_Controller_Action { public function preDispatch(){ // do the logic } } 

И теперь каждому из ваших контроллеров нужно только расширить MyController, и вы в безопасности.

То, как я сделал это в одной реализации, было создание файла с именем Auth.php в моем пути к приложению. Затем я открыл каждый контроллер, который хотел защитить, и добавил строку

 include_once APPLICATION_PATH . '/Auth.php'; 

к методу init () перед вызовом parent :: init ().

Что касается самого файла Auth.php, он в основном использует Zend_Auth для аутентификации. При успехе я бы сохранил личность пользователя для последующего использования в приложении

 $this->view->assign('myIdentity', Zend_Auth::getInstance()->getIdentity()); 

В случае сбоя я бы перенаправил страницу входа и передал некоторые параметры, чтобы страница входа в систему знала, куда мне отправить сообщение после входа в систему.

Это не изящное решение, но оно надежное и относительно быстрое и простое в использовании.