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

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

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

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

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

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

5.2.6.10 разрешить

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

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

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

Я добавил поле «пароль» в таблицу моих пользователей и установил для каждого пользователя пароль «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