2011-02-09 9 views
6

Come proteggere globalmente tutti i miei controller (ad eccezione del controller di accesso) per garantire che la mia applicazione sia protetta in tutti i punti (nessuna backdoor nascosta per chiamate jax, ecc.). Ho pensato che potrei metterlo nel mio file di bootstrap, ma questo non mi sembra giusto? Sto cercando di evitare di aggiungere alcun codice a ciascun controller.Utilizzo di Zend_Auth per proteggere tutti i controller

Suggerimenti?

risposta

11

modifica: questo è un complemento della risposta di @singles.

Devi capire che ci sono 2 cose diverse. Auth e Acl. Auth ti dice chi è l'utente e puoi ad esempio reindirizzare l'utente che non ha Auth al tuo login controller e impostare un auth identity dopo il login. allora il sistema Acl prendere sì/no decisioni basate sui dati Auth (potrebbe essere l'id utente o è il ruolo, memorizzati nella memoria Auth.

Sulla bella soluzione è quella di avere 2 controllori plugin (registrato in buona ordine sul bootstrap, Auth quindi Acl.) Se non si utilizzano i plug-in Controller, sarà necessario richiamare l'Acl in ogni controller, se necessario, se necessario, quindi utilizzare i plug-in.

Implementare il preDispatch() in voi Auth plug-in per impostare ad esempio un'identità anonima se non si dispone di ritorno di identità da Zend_Auth. Si tratta di un frammento di codice di un vero e proprio:

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

E per la Acl controllore plug Il compito è pure in preDispatch(). È possibile avviare un controllo ACL per ogni URL richiesto (quindi per ogni richiesta utente, anche ajax). Ecco un frammento parziale, quindi questo solo un esempio di come si possa gestire le cose:

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

e in questo sistema l'ultima parte importante è il LoginController dove in caso di login di successo si dovrebbe initate il record di identità:

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

Buoni esempi. +1 – singles

+0

+1 Mi piace l'idea di utente 'anonimo', e prometto che lo userei nei miei lavori :) – tawfekov

+0

@singles grazie, questa è la soluzione che stavo cercando! –

0

Beh, è ​​necessario disporre di un punto di ingresso al sistema :)

Ciò può essere ottenuto estendendo Zend_Controller_Action, diciamo:

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

E ora ogni controller ha solo bisogno di estendere la MyController e sei sicuro.

+1

In questa soluzione, in ogni app è necessario estendere il controller personalizzato. Penso che il plug-in del controller anteriore sia la soluzione migliore: puoi registrarlo quando vuoi e in quale app ZF desideri senza modifiche del codice esistente. – singles

+0

Vero, totalmente d'accordo. I plugin sono magici una volta che li conosci :) Upvoted la tua soluzione. – usoban

4

È necessario scrivere il plug-in ACL per quello e registrarlo sul front controller. Se si implementa tale funzionalità come plug-in, si avrà la flessibilità di utilizzarlo nella prossima applicazione, senza la necessità di estendere ciascun controller dal controller personalizzato.

Risorse:
1. Front Controller Plugins in Zend Framework - come plug-in funzionano ZF
2. Zend_Acl/Zend_Auth example scenario - uno dei tanti possibili implementazioni di ACL plugin. 3. Google - e molte altre risorse

0

Il modo in cui l'ho fatto in un'implementazione era di creare un file chiamato Auth.php nel percorso dell'applicazione. Poi ho aperto ogni controller che volevo essere protetto e aggiunto la linea di

include_once APPLICATION_PATH . '/Auth.php'; 

al metodo init() prima di chiamare parent :: init().

Come per il file Auth.php, in pratica utilizza Zend_Auth per l'autenticazione. In caso di successo salverei l'identità degli utenti per un uso successivo nell'applicazione

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

In caso di fallimento avrei reindirizzamento alla pagina di login e passare alcuni params in modo che la pagina di login sa dove inviare me una volta che sono login

Questa non è una soluzione elegante ma è affidabile e relativamente veloce e facile da implementare.

Problemi correlati