Альтернативные источники аутентификации в CakePHP (LDAP)


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

Похоже, что Cake обрабатывает пароли только тогда, когда они существуют в локальной базе данных. Кулинарная книга торта предполагает, что вы можете рассказать об этом по-другому контроллер/модель/объект для обеспечения процедуры авторизации с помощью переменной $this->Auth->authorize, однако, глядя на код (в частности, функция Auth::startup()), похоже, что 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.

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

Author: nickf, 2009-09-09

3 answers

Предполагая, что вы просто привязываетесь к 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 в своем приложении или следуйте инструкциям здесь.

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

 8
Author: deizel, 2009-09-09 14:05:05

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

5.2.6.10 авторизовать

Обычно компонент AuthКомпонент пытается проверить точность введенных вами учетных данных для входа, сравнивая их с тем, что было сохранено в вашей модели пользователя. Однако бывают случаи, когда вам может потребоваться выполнить некоторую дополнительную работу по определению надлежащих учетных данных.

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

 1
Author: deceze, 2009-09-09 02:15:30

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

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

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

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

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

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

Это означает, что теперь первый шаг cake всегда будет проходить (при условии, что имя пользователя существует в таблице). То 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
 0
Author: nickf, 2009-09-09 03:21:14