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

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

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

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


person nickf    schedule 09.09.2009    source источник


Ответы (3)


Предполагая, что вы просто привязываетесь к 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 должны< /em> должен быть в конфигурации database.php, а LdapAuthComponent должен быть адаптирован для использования настраиваемых сопоставлений полей, это не требования «просто сделать это». :)

person deizel    schedule 09.09.2009

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

5.2.6.10 авторизация

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

Однако это не должно быть проблемой, поскольку детали LDAP должны быть абстрагированы в модели. Cake по-прежнему будет проверять модель на наличие имени пользователя и пароля, но он получает ответы прозрачно из каталога LDAP. Вам просто нужно реализовать LDAP источник данных для модели. Может быть, эти два < href="http://bakery.cakephp.org/articles/view/ldap-models-in-cakephp" rel="nofollow noreferrer">статьи помогут вам начать работу.

person deceze♦    schedule 09.09.2009

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

Я добавил поле «пароль» в свою таблицу пользователей и установил для всех пароль «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
person nickf    schedule 09.09.2009