2009-09-09 2 views
6

Sto lavorando a un progetto CakePHP e attualmente sto sviluppando la parte di autenticazione dell'utente. Il problema è che le mie informazioni di autenticazione (es: le password) non sono memorizzate nel mio database - la fonte di autenticazione è LDAP ma la mia domanda si applica ugualmente a qualsiasi fonte non di database.Fonti di autenticazione alternative in CakePHP (LDAP)

sembra come se Cake gestisce solo le password quando esistono nel database locale. The Cake Cookbook suggests che è possibile specificare un controller/modello/oggetto diverso per fornire una procedura di autorizzazione utilizzando la variabile $this->Auth->authorize, tuttavia guardando il codice (in particolare the Auth::startup() function) sembra che Cake tenterà sempre di interrogare il database primo, verificando un nome utente/password corrispondente, prima di esaminare l'oggetto alternativo specificato con Auth->authorize. Cioè, la modifica di authorize aggiunge solo un filtro di secondo livello, non sostituisce la ricerca nel database.

// The process 
1. User provides details 
2. Cake checks the database 
3. If OK, then check the custom object method 
4. If OK, return true 

// What I'd like: 
1. User provides details. 
2. Check the custom object method 
3. If OK, return true 
4. Profit. 

Qualche idea su come eseguire questa operazione, si spera senza l'hacking dei file principali?

+0

+1 per profitto ... – Stephen

risposta

8

Supponendo che si sta semplicemente di legame con LDAP e archiviano/recupero dei dati utente da MySQL, questo approccio funzionerà come un "ponte" che creerà automaticamente gli account per gli accessi di successo:

// app/controllers/components/ldap_auth.php 
<?php 
App::import('Component', 'Auth'); 
class LdapAuthComponent extends AuthComponent { 
/** 
* Don't hash passwords 
*/ 
    function hashPasswords($data){ 
     return $data; 
    } 
/** 
* We will initially identify the user 
*/ 
    function identify($user=null, $conditions=null) { 
     // bind credentials against ldap 
     $ldapUser = $this->_ldapAuth($user); // do your stuff 
     if (!$ldapUser) { 
      return null; // if bind fails, then return null (as stated in api) 
     } 
     // get the cake model you would normally be authenticating against 
     $model =& $this->getModel(); // default is User 
     // check for existing User in mysql 
     $user = $model->find('first', array('conditions' => array(
      'username' => $ldapUser['cn'] 
     )); 
     // if no existing User, create a new User 
     if (!$user) { 
      $user = $model->save(array('User' => array(
       'username' => $ldapUser['cn'], 
       // .. map needed ldap fields to mysql fields .. 
      ))); 
      if (!$user) { 
       $this->cakeError('ldapCreateUser'); 
      } 
      // pass the id of the newly created User to Auth's identify 
      return parent::identify($model->id, $conditions); 
     } 
     // pass the id of the existing User to Auth's identify 
     return parent::identify($user[$this->userModel][$model->primaryKey], $conditions); 
    } 
/** 
* Lets check LDAP 
* 
* @return mixed Array of user data from ldap, or false if bind fails 
*/ 
    function _ldapAuth($user) { 
     $username = $user[$this->userModel][$this->fields['username']]; 
     $password = $user[$this->userModel][$this->fields['password']]; 
     // use the php ldap functions here 
     return $ldapUser; 
    } 
} 
?> 

per utilizzare, sostituire tutti i riferimenti a Auth con LdapAuth nell'applicazione o seguire la instructions here.

Nota che, anche se il _ldapAuth() metodo protetto potrebbe prelevata è fuori per un modello LdapUser, e quel modello dovrebbe leggere da un LdapSource, e il server LDAP impostazioni di connessione dovrebbero essere nel database.php config, e la LdapAuthComponentdovrebbe essere adattato per utilizzare le mappature di campo configurabili,, questi non sono requisiti per "just get it done". :)

1

Auth::authorize non è davvero una sostituzione per i dati del modello, si aggiunge solo ad esso.

5.2.6.10 authorize

Normalmente, l'AuthComponent tenterà di verificare che le credenziali di accesso che hai inserito sono precisi confrontandole con ciò che è stato memorizzato nel modello utente. Tuttavia, ci sono momenti in cui si potrebbe voler fare qualche lavoro aggiuntivo nel determinare le credenziali appropriate.

Questo non dovrebbe essere un problema, però, dal momento che i dettagli LDAP devono essere astratte via nel modello. Cake controllerà comunque il modello per nome utente e password, ma otterrà le risposte in modo trasparente da una directory LDAP. Hai solo bisogno di implementare un LDAP datasource per il modello. Forse questi twoarticles possono iniziare.

0

sono stato in grado di incidere in tutto il modo Cake lo fa in un modo relativamente poco raccomandabile, ma probabilmente accettabile.

ho aggiunto un campo "password" sul mio tavolo degli utenti e impostare la password di tutti per "un" (anche se è possibile utilizzare qualsiasi cosa).

poi ho aggiunto una funzione di hashing personalizzato nel mio modello:

function hashPasswords($data) { 
    $data['User']['password'] = 'a'; 
    return $data; 
} 

e dissi a mio controller per utilizzare tale modello per l'hashing:

$this->Auth->authenticate = ClassRegistry::init('User'); 

Ciò significa che ora primo passo che della torta sarà sempre passare (supponendo che il nome utente esista nella tabella). La funzione authorize ora può fare le sue cose e fare il tuo controllo corretto usando qualsiasi metodo tu voglia.

E 'fondamentalmente cambiato il processo a questo:

// The process 
1. User provides details 
2. Cake checks the database **and always returns OK** 
3. If OK, then check the custom object method 
4. If OK, return true