2010-08-02 2 views
9

Я использую Zend_Auth для аутентификации на веб-портале.Zend_Auth: разрешить пользователю регистрироваться в нескольких таблицах/тождествах

нормальной «пользователи» MySql таблицу с колонкой login и password получает опрошена против, и пользователь вошел в систему.

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

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

Каждая из трех групп входа имеет свою собственную форму входа и выход из системы.

На данный момент, у меня есть один, простой Zend_Auth логина, взятых из какого-то учебника и немного измененные, который выглядит примерно так:

function login($user, $password) 
{ 

$auth = Zend_Auth::getInstance(); 
$storage = new Zend_Auth_Storage_Session(); 

$auth->setStorage($storage); 

$adapter = new Zend_Auth_Adapter_DbTable(....); 

$adapter->setIdentity($username)->setCredential($password); 

$result = $auth->authenticate($adapter); 

if ($result->isValid()) 
......... success! 
else 
.... fail! 

где бы я должен начать делать это служить и адресом отдельные «вошедшие в систему» ​​состояния для трех групп? Моя идея состоит в том, что я хотел бы поделиться сеансом и управлять аутентификацией отдельно.

Возможно ли это? Может быть, есть простой префикс, который делает это проще? Существуют ли какие-либо учебники или ресурсы по этой проблеме?

Я относительный новичок в Zend Framework.

+0

вам нужно иметь отдельные идентификаторы для каждой группы делать? Или это просто вопрос аутентификации против другой таблицы? – Gordon

+0

@ Gordon они должны быть отдельными идентификаторами (скажем, пользователями CMS, оптовиками и конечными пользователями). В то же время я мог бы все три вещи. –

+0

Prior ZF это был домен PEAR :: LiveUser. http://devzone.zend.com/node/view/id/1001 – mario

ответ

10

Вы должны создать свой собственный Zend_Auth_Adapter. Этот адаптер попытается аутентифицировать ваши три ресурса и будет отмечать его в частной переменной-члене, поэтому вы можете узнать, какие попытки входа были успешно завершены.

Чтобы создать свой адаптер Auth, вы можете взять за основу Zend_Auth_Adapter_DbTable.

Итак, в __construct вместо прохода только один адаптер DbTable вы можете передать три адаптера, используемые в каждом ресурсе. Вы будете делать это только в том случае, если каждый из них использует разные ресурсы, например, LDAP или даже другую базу данных, если нет, вы можете передать только один адаптер и установить три разных имени таблицы в параметрах конфигурации.

Вот пример из Zend_Auth_Adapter_DbTable:

/** 
    * __construct() - Sets configuration options 
    * 
    * @param Zend_Db_Adapter_Abstract $zendDb 
    * @param string     $tableName 
    * @param string     $identityColumn 
    * @param string     $credentialColumn 
    * @param string     $credentialTreatment 
    * @return void 
    */ 
    public function __construct(Zend_Db_Adapter_Abstract $zendDb, $tableName = null, $identityColumn = null, 
           $credentialColumn = null, $credentialTreatment = null) 
    { 
     $this->_zendDb = $zendDb; 

     // Here you can set three table names instead of one 
     if (null !== $tableName) { 
      $this->setTableName($tableName); 
     } 

     if (null !== $identityColumn) { 
      $this->setIdentityColumn($identityColumn); 
     } 

     if (null !== $credentialColumn) { 
      $this->setCredentialColumn($credentialColumn); 
     } 

     if (null !== $credentialTreatment) { 
      $this->setCredentialTreatment($credentialTreatment); 
     } 
    } 

Метод ниже, от Zend_Auth_Adapter_DbTable, попробуйте для проверки подлинности одной таблицы, вы можете изменить его, чтобы попытаться в трех таблицах, и для каждого, когда вы получаете успех и , вы устанавливаете это как флаг в переменной частного члена. Что-то вроде $ result ['group1'] = 1; Вы будете устанавливать 1 для каждой успешной попытки входа в систему.

/** 
* authenticate() - defined by Zend_Auth_Adapter_Interface. This method is called to 
* attempt an authentication. Previous to this call, this adapter would have already 
* been configured with all necessary information to successfully connect to a database 
* table and attempt to find a record matching the provided identity. 
* 
* @throws Zend_Auth_Adapter_Exception if answering the authentication query is impossible 
* @return Zend_Auth_Result 
*/ 
public function authenticate() 
{ 
    $this->_authenticateSetup(); 
    $dbSelect = $this->_authenticateCreateSelect(); 
    $resultIdentities = $this->_authenticateQuerySelect($dbSelect); 

    if (($authResult = $this->_authenticateValidateResultset($resultIdentities)) instanceof Zend_Auth_Result) { 
     return $authResult; 
    } 

    $authResult = $this->_authenticateValidateResult(array_shift($resultIdentities)); 
    return $authResult; 
} 

Вы вернётесь действительный $ authresult только если один из трех попыток входа в систему были успешно аутентификацией.

Теперь в контроллере, после того, как вы пытаетесь войти в систему:

public function loginAction() 
{ 
    $form = new Admin_Form_Login(); 

    if($this->getRequest()->isPost()) 
    { 
     $formData = $this->_request->getPost(); 

     if($form->isValid($formData)) 
     { 

      $authAdapter = $this->getAuthAdapter(); 
       $authAdapter->setIdentity($form->getValue('user')) 
          ->setCredential($form->getValue('password')); 
       $result = $authAdapter->authenticate(); 

       if($result->isValid()) 
       { 
        $identity = $authAdapter->getResult(); 
        Zend_Auth::getInstance()->getStorage()->write($identity); 

        // redirect here 
       }   
     } 

    } 

    $this->view->form = $form; 

} 

private function getAuthAdapter() 
{ 
    $authAdapter = new MyAuthAdapter(Zend_Db_Table::getDefaultAdapter()); 
    // Here the three tables 
    $authAdapter->setTableName(array('users','users2','users3')) 
       ->setIdentityColumn('user') 
       ->setCredentialColumn('password') 
       ->setCredentialTreatment('MD5(?)'); 
    return $authAdapter;  
} 

Ключевым моментом здесь является линия ниже, что будет implemeted в пользовательском адаптере Идент:

$identity = $authAdapter->getResult(); 

Вы можете взять за основу эту форму Zend_Auth_Adapter_DbTable:

/** 
    * getResultRowObject() - Returns the result row as a stdClass object 
    * 
    * @param string|array $returnColumns 
    * @param string|array $omitColumns 
    * @return stdClass|boolean 
    */ 
    public function getResultRowObject($returnColumns = null, $omitColumns = null) 
    { 
     // ... 
    } 

Это возвращение строки сопоставляются в регистрационной а при успешной аутентификации. Итак, вы создадите метод getResult(), который может вернуть эту строку, а также флаги $ this-> result ['groupX']. Что-то вроде:

public function authenticate() 
{ 
    // Perform the query for table 1 here and if ok: 
    $this->result = $row->toArrray(); // Here you can get the table result of just one table or even merge all in one array if necessary 
    $this->result['group1'] = 1; 

    // and so on... 
    $this->result['group2'] = 1; 

    // ... 
    $this->result['group3'] = 1; 

    // Else you will set all to 0 and return a fail result 
} 

public function getResult() 
{ 
    return $this->result; 
} 

В конце концов вы можете использовать Zend_Acl, чтобы взять под свой контроль над своими взглядами и другими действиями. Так как вы будете иметь флаги в Zend Auth хранилище, вы можете использовать не как ролях:

$this->addRole(new Zend_Acl_Role($row['group1'])); 

Вот некоторые ресурсы:

http://framework.zend.com/manual/en/zend.auth.introduction.html

http://zendguru.wordpress.com/2008/11/06/zend-framework-auth-with-examples/

http://alex-tech-adventures.com/development/zend-framework/61-zendauth-and-zendform.html

http://alex-tech-adventures.com/development/zend-framework/62-allocation-resources-and-permissions-with-zendacl.html

http://alex-tech-adventures.com/development/zend-framework/68-zendregistry-and-authentication-improvement.html

+0

Очень приятно. Я посмотрю на это, и если я смогу с ним работать, немедленно его реализовать. Это может занять несколько дней, но я обязательно вернусь с обратной связью. –

+0

+1 пользовательский автоответчик, вероятно, будет лучшей идеей.для тех, кто может делать то, что на какой части использовать zend_acl – robertbasic

+0

@Pekka Вы достигли этого? Какие-то проблемы? –

1

Почему бы не просто создать представление, объединяющее все 3 таблицы, а затем пройти проверку подлинности против этого представления?

+0

Это не даст мне возможность войти в систему в любой из трех таблиц одновременно. –

+0

спасибо, это очень полезно для меня –

3

Я получил некоторое вдохновение от Zym_Auth_Adapter_Chain, но немного изменил его, чтобы он не останавливался на первом адаптере, который успешно возвращается.

require_once 'Zend/Auth/Adapter/Interface.php'; 
require_once 'Zend/Auth/Result.php'; 

class My_Auth_Adapter_Chain implements Zend_Auth_Adapter_Interface 
{ 
    private $_adapters = array(); 

    public function authenticate() 
    { 
     $adapters = $this->getAdapters(); 

     $results  = array(); 
     $resultMessages = array(); 
     foreach ($adapters as $adapter) { 
      // Validate adapter 
      if (!$adapter instanceof Zend_Auth_Adapter_Interface) { 
       require_once 'Zend/Auth/Adapter/Exception.php'; 
       throw new Zend_Auth_Adapter_Exception(sprintf(
        'Adapter "%s" is not an instance of Zend_Auth_Adapter_Interface', 
       get_class($adapter))); 
      } 

      $result = $adapter->authenticate(); 

      if ($result->isValid()) { 
       if ($adapter instanceof Zend_Auth_Adapter_DbTable) { 
        $results[] = $adapter->getResultRowObject(); 
       } 
       else { 
        $results[] = $result->getIdentity(); 
       } 
      } 
      else { 
       $resultMessages[] = $result->getMessages(); 
      } 
     } 
     if (!empty($results)) { 
      // At least one adapter succeeded, return SUCCESS 
      return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $results, $resultMessages); 
     } 

     return new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, $resultMessages); 
    } 

    public function getAdapters() 
    { 
     return $this->_adapters; 
    } 

    public function addAdapter(Zend_Auth_Adapter_Interface $adapter) 
    { 
     $this->_adapters[] = $adapter; 
     return $this; 
    } 

    public function setAdapters(array $adapters) 
    { 
     $this->_adapters = $adapters; 
     return $this; 
    } 
} 

Для вызова из контроллера вы просто создаете цепочку, то адаптеры, которые вы хотите использовать (в вашем случае это, вероятно, будет адаптер DB на таблицу сущностей), и, наконец, пройти адаптеры к цепи ,

$db = Zend_Db_Table::getDefaultAdapter(); 

// Setup adapters 
$dbAdminsAdapter = new Zend_Auth_Adapter_DbTable($db, 'admins');  
$dbAdminsAdapter->setIdentityColumn('login') 
       ->setCredentialColumn('password') 
       ->setIdentity($login) 
       ->setCredential($password); 

$dbUsersAdapter = new Zend_Auth_Adapter_DbTable($db, 'users'); 
$dbUsersAdapter->setIdentityColumn('login') 
       ->setCredentialColumn('password') 
       ->setIdentity($login) 
       ->setCredential($password); 
... 

// Setup chain 
$chain = new My_Auth_Adapter_Chain(); 
$chain->addAdapter($dbAdminsAdapter) 
     ->addAdapter($dbUsersAdapter); 

// Do authentication 
$auth = Zend_Auth::getInstance(); 
$result = $auth->authenticate($chain); 
if ($result->isValid()) { 
    // succesfully logged in 
} 

Это просто базовый пример кода, вы, вероятно, хотите использовать setCredentialTreatment также на DbTable адаптеры ...

Достоинством такого подхода является то, что он будет тривиальным, чтобы добавить другие существующие адаптеры для другого формы аутентификации (то есть OpenID) в цепочку позже ...

Недостаток: как вы получите массив в результате каждого вызова Zend_Auth :: getInstance() -> getIdentity() ;. Разумеется, вы можете изменить это в адаптере Chain, но это вам осталось: p.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я действительно не думаю, что было бы разумно сделать это таким образом. Чтобы заставить его работать, вы должны использовать один и тот же логин и пароль в разных таблицах, поэтому, если у пользователя более 1 роль (идентификатор) изменяется его пароль, вам нужно убедиться, что это изменение распространяется на все таблицы идентификации, где это у пользователя есть учетная запись. Но я перестану ныть сейчас: p.

2

Поскольку Zend_Auth является одноэлементным, создание пользовательских адаптеров auth для каждого источника аутентификации разрешает первую половину этой проблемы. Вторая половина проблемы заключается в том, что вы хотите иметь возможность входа одновременно с несколькими учетными записями: один из каждого источника аутентификации.

Я спросил similar question recently. Решение состояло в том, чтобы расширить Zend_Auth, как показано в принятом ответе. Затем я инициализирую различные типы аутентификации в своем бутстрапе.

protected function _initAuth() 
{ 
    Zend_Registry::set('auth1', new My_Auth('auth1')); 
    Zend_Registry::set('auth2', new My_Auth('auth2')); 
    Zend_Registry::set('auth3', new My_Auth('auth3')); 
} 

Таким образом, вместо того, чтобы синглтон Zend_Auth::getInstance() вы будете использовать Zend_Registry::get('auth1') и т.д.

 Смежные вопросы

  • Нет связанных вопросов^_^