2011-02-09 12 views
6

¿Cómo puedo asegurar globalmente todos mis controladores (excepto mi controlador de inicio de sesión) para asegurar que mi aplicación sea segura en todos los puntos (sin puerta trasera oculta para llamadas ajax, etc.). Pensé que podría ponerlo en mi archivo bootstrap, pero esto no se siente bien? Estoy tratando de evitar agregar cualquier código a cada controlador.Usando Zend_Auth para asegurar todos los controladores

Sugerencias?

Respuesta

11

editar: esto es un complemento de @singles response.

Debe comprender que hay 2 cosas diferentes. Auth y Acl. Auth le dice quién es el usuario y puede, por ejemplo, redirigir al usuario que no tiene autenticación a su controlador de inicio de sesión y establecer una identidad de autenticación después del inicio de sesión. entonces el sistema Acl aceptar un sí/no hay decisiones basadas en los datos de autenticación de acceso (podría ser el ID de usuario o es papel, almacenada en el almacenamiento de autenticación.

En buena solución es tener 2 controladores de plugins (registrada en el buen ordenar en el bootstrap, Auth y Acl). Si no usa los complementos de Controller, deberá llamar a Acl check en cada controlador, cuando sea necesario. Si siempre lo necesita, use complementos.

Implemente el preDispatch() en usted Auth plugin para establecer, por ejemplo, una identidad anónima si no tiene un retorno de identidad de Zend_Auth. Este es un fragmento de código de uno de verdad:

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,)); 
    } 
(...) 

Y para el Acl controlador plug-in la tarea es así en preDispatch(). Puede iniciar una comprobación de acl para cada URL solicitada (por lo que para cada solicitud de usuario, incluso ajax). He aquí un fragmento parcial, por lo que este sólo un ejemplo de cómo se puede manejar las cosas:

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; 
(...) 

y en este sistema la última parte importante es la LoginController donde, en caso de inicio de sesión exitoso debe initate el registro de identidad:

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

Buenos ejemplos. +1 – singles

+0

+1 me gusta la idea del usuario 'anónimo', y prometo que lo usaría en mis trabajos :) – tawfekov

+0

@singles gracias, ¡esta es la solución que estaba buscando! –

0

Bueno, es necesario tener un punto de entrada al sistema :)

Esto se puede lograr mediante la extensión de Zend_Controller_Action, digamos:

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

Y ahora cada uno de los controladores sólo tiene que extender MyController y estás seguro.

+1

En esa solución, en cada aplicación deberá extender el controlador personalizado. Creo que ese plugin de controlador frontal será la mejor solución: puede registrarlo cuando lo desee y en qué aplicación ZF desee sin modificaciones del código existente. – singles

+0

Es cierto, totalmente de acuerdo. Los complementos son mágicos una vez que los conoces :) Upvoted tu solución. – usoban

4

Debe escribir el complemento ACL para eso y registrarlo en el controlador frontal. Si implementa dicha funcionalidad como un complemento, tendrá flexibilidad para usarlo en su próxima aplicación, sin necesidad de extender cada controlador desde su controlador personalizado.

Recursos:
1. Front Controller Plugins in Zend Framework - cómo plugins trabajan en ZF
2. Zend_Acl/Zend_Auth example scenario - una de las muchas posibles implementaciones de ACL Plugin.
3. Google - y gran cantidad de otros recursos

0

La forma en que lo hice en una implementación era crear un archivo llamado auth.php en mi ruta de la aplicación. Entonces abrí cada controlador que quería ser protegidos y añadí la línea

include_once APPLICATION_PATH . '/Auth.php'; 

al método init() antes de llamar a los padres :: init().

En cuanto al archivo Auth.php, básicamente utiliza Zend_Auth para autenticarse. En caso de éxito que ahorraría la identidad del usuario para su uso posterior en la aplicación

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

En caso de fallo Me redirigir a la página de inicio de sesión y pasar algunos parametros para que la página de inicio de sesión sabe dónde enviarme una vez que estoy Inicie sesión.

Esta no es una solución elegante, pero es confiable y relativamente rápida y fácil de implementar.

Cuestiones relacionadas