Использование Zend_Auth для защиты всех контроллеров - PullRequest
6 голосов
/ 09 февраля 2011

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

Предложения

Ответы [ 4 ]

11 голосов
/ 09 февраля 2011

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

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

Хорошим решением является наличие 2 плагинов контроллеров (зарегистрированных в хорошем порядке на начальной загрузке, Auth затем 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;
(...)

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

(...)
$auth = Zend_Auth::getInstance();
Zend_Session::regenerateId();
$storage = $auth->getStorage();
$rowobject = $authAdapter->getResultRowObject(null,'passwd');
$storage->write((array)$rowobject);
(...)
4 голосов
/ 09 февраля 2011

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

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

0 голосов
/ 09 февраля 2011

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

include_once APPLICATION_PATH . '/Auth.php';

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

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

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

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

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

0 голосов
/ 09 февраля 2011

Ну, вам нужна точка входа в вашу систему:)

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...