2009-09-09 3 views
6

Я работаю над проектом CakePHP и в настоящее время создаю часть аутентификации пользователя. Проблема в том, что мои данные аутентификации (то есть: пароли) не хранятся в моей базе данных - источником аутентификации является LDAP, но мой вопрос применим в равной степени к любому источнику без базы данных.Альтернативные источники аутентификации в CakePHP (LDAP)

Похоже, что Cake обрабатывает пароли только в том случае, если они существуют в локальной базе данных. The Cake Cookbook suggests, что вы можете указать ему другой контроллер/модель/объект для предоставления процедуры авторизации с использованием переменной $this->Auth->authorize, однако, глядя на код (в частности, the Auth::startup() function), похоже, что Cake будет всегда пытаться запросить базу данных сначала, проверяя совпадающее имя пользователя/пароль, прежде чем смотреть на альтернативный объект, указанный вами с помощью Auth->authorize. То есть, изменение authorize только добавляет фильтр второго уровня, он не заменяет поиск базы данных.

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

Любые идеи о том, как это сделать, надеюсь, без взлома файлов ядра?

+0

+1 для прибыли ... – Stephen

ответ

8

Предполагая, что вы просто связывания с LDAP и хранения/извлечения данных пользователя из MySQL, этот подход будет работать в качестве «моста», который будет автоматически создавать учетные записи для успешного входа в систему:

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

для использования, заменить все ссылки на Auth с LdapAuth в приложении или следовать instructions here.

Обратите внимание, что хотя защищаемый _ldapAuth() метода может быть абстрагирован к LdapUser модели, а модель должна чтения из LdapSource, а сервер LDAP настройки соединения должна быть в database.php конфигурации, и LdapAuthComponentдолжен быть адаптирован для использования конфигурируемых сопоставлений полей, это не требования к «просто сделайте это». :)

1

Auth::authorize действительно не заменяет данные модели, он просто добавляет к нему.

5.2.6.10 authorize

Обычно AuthComponent будет пытаться проверить, что регистрационные данные вы Введенные точны, сравнивая их с тем, что это был сохранен в модели пользователя. Однако есть моменты, когда вы можете сделать дополнительную работу по определению правильных учетных данных.

Это не должно быть проблемой, поскольку детали LDAP должны быть абстрагированы от модели. Cake по-прежнему будет проверять модель для имени пользователя и пароля, но она получает свои ответы прозрачно из каталога LDAP. Вам просто нужно реализовать LDAP datasource для модели. Возможно, эти twoarticles могут помочь вам.

0

Я был в состоянии взломать путь, как Торт делает это в относительно изворотливом, но, вероятно, приемлемом пути.

Я добавил поле «пароль» в таблицу моих пользователей и установил для каждого пользователя пароль «a» (хотя вы могли бы использовать что-либо).

Затем я добавил пользовательские функции хэширования в моей модели:

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

И сказал мой контроллер использовать эту модель для хеширования:

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

Это означает, что теперь первый шаг этого торта всегда будет проходить (предполагая, что имя пользователя существует в таблице). Функция authorize теперь может выполнить свою задачу и выполнить вашу проверку, используя любой метод, который вам нужен.

Это в основном изменили процесс к этому:

// 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 
Смежные вопросы