2009-09-09 16 views
6

Estoy trabajando en un proyecto de CakePHP y actualmente estoy creando la parte de autenticación del usuario. El problema es que mi información de autenticación (es decir, las contraseñas) no está almacenada en mi base de datos: la fuente de autenticación es LDAP, pero mi pregunta se aplica por igual a cualquier fuente que no sea de base de datos.Fuentes de autenticación alternativas en CakePHP (LDAP)

Parece que Cake solo maneja las contraseñas cuando existen en la base de datos local. The Cake Cookbook suggests que puede indicarle un controlador/modelo/objeto diferente para proporcionar un procedimiento de autorización utilizando la variable $this->Auth->authorize; sin embargo, al mirar el código (específicamente the Auth::startup() function), parece que Cake siempre intentará consultar la base de datos primero, buscando un nombre de usuario/contraseña coincidente, antes de mirar el objeto alternativo que especificó con Auth->authorize. Es decir, cambiar authorize solo agrega un filtro de segundo nivel, no reemplaza la búsqueda de la base de datos.

// 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. 

Cualquier ideas sobre cómo hacer esto, es de esperar sin cortar los archivos del núcleo?

+0

+1 por Profit ... – Stephen

Respuesta

8

Suponiendo que está simplemente de unión frente a LDAP y está almacenando/recuperación de datos de usuario de MySQL, este enfoque va a funcionar como un "puente" que creará automáticamente las cuentas para las conexiones con éxito:

// 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; 
    } 
} 
?> 

para el uso, cambie todas las referencias a Auth con LdapAuth en su aplicación o seguir el instructions here.

Tenga en cuenta que aunque el _ldapAuth() método protegido podría abstraerse a un modelo LdapUser, y ese modelo debe leer de un LdapSource, y el servidor LDAP configuración de conexión deben estar en el database.php config, y el LdapAuthComponentsi se adaptara para usar asignaciones de campos configurables, estos no son requisitos para "simplemente hacerlo". :)

1

Auth::authorize de hecho no es un reemplazo de los datos del modelo, simplemente se agrega.

5.2.6.10 authorize

Normalmente, el AuthComponent intentará verificar que las credenciales de inicio de sesión que ha introducido son exactos, comparándolos con lo que se ha almacenado en su modelo de usuario. Sin embargo, hay ocasiones en las que es posible que desee hacer algún trabajo adicional para determinar las credenciales adecuadas.

Eso no debería ser un problema, ya que los detalles de LDAP deben abstraerse en el modelo. Cake seguirá revisando el modelo de nombre de usuario y contraseña, pero está obteniendo sus respuestas de forma transparente desde un directorio LDAP. Solo necesita implementar un LDAP datasource para el modelo. Tal vez estos twoarticles pueden comenzar.

0

Pude hackear la forma en que Cake lo hace de una manera relativamente dudosa, pero probablemente aceptable.

Agregué un campo de "contraseña" en mi tabla de usuarios y configuré la contraseña de todos en "a" (aunque podría usar cualquier cosa).

Luego añade una función hash personalizado en mi modelo:

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

y le dijo a mi controlador de usar ese modelo para hash:

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

Esto significa que ahora el primer paso de esa torta pasará siempre (suponiendo que el nombre de usuario existe en la tabla). La función authorize ahora puede hacer lo suyo y hacer su verificación adecuada utilizando el método que desee.

Es básicamente cambió el proceso para esto:

// 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 
Cuestiones relacionadas