Zend: autenticarsi con credenziali di phpbb3
L’adapter l’ho costruito e testo utilizzando Zend Framework 1.8.4, l’architettura del mio progetto Zend è di base e si può creare facilmente con Zend_Tool. La versione del framework phpass che ho utilizzato è la 0.1 .
Per prima cosa, dopo aver creato il mio applicativo basato sulle librerie di Zend, recupero il framework phpass dal sito del progetto.
Scompatto l’archivio e salvo nella cartella library
della mia applicazione Zend il file PasswordHash.php
.
Il framework, di base, utilizza un identificatore del tipo di hash uguale a “$P$”, phpbb3 invece utilizza “$H$” per cui bisogna fare la sostituzione di questa stringa alla riga 94 e 108 (circa) del file PasswordHash.php
.
Ora posso costruire il mio adapter. Ho creato un file php, MyAuthAdapter.php
all’interno della cartella library.
Si può anche salvare l’adapter creando il file in una struttura di directory, per cui: library/My/Auth/Adapter.php
, io ho preferito creare solamente un file senza la struttura delle directory tipica di Zend, se però avessi molte più librerie allora è bene tenere un certo ordine.
Questo è l’adapter:
_username=$username;
$this->_password=$password;
//Il tipo di utente sul forum
//posso far fare l'autenticazione solo agli amministratori o al tipo di utente fornito
$this->_usertype=$usertype;
}
public function authenticate()
{
//Carico tramite Zend_Loader il framework phpass
if(Zend_Loader::isReadable('PasswordHash.php')){
Zend_Loader::loadFile('PasswordHash.php');
//istanzio il mio oggetto phpass
$phpass = new PasswordHash();
//istanzio l'oggetto Zend_Db_Table in modo da recuperare i dati dal database
$db = Zend_Db_Table::getDefaultAdapter();
$select = $db->select()
->from('phpbb_users')
->where("username = '$this->_username'");
$row = $db->fetchRow($select);
if($row){
if($row['user_type'] == $this->_usertype){
// con la funzione CheckPassword dell'oggetto phpass posso controllare
// se la password fornita corrisponde all'hash presente nel database
$pass = $phpass->CheckPassword($this->_password, $row['user_password']);
if($pass)
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS);
else
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID);
} else {
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE);
}
} else {
return new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND);
}
} else {
//se non esiste il file o è illeggibile ritorno un error
throw new Exception("PasswordHash.php non esiste o è illeggibile.");
}
}
}
Non commento niente di più in quanto già di per se mi sembra esplicativo.
Per sfruttare poi questo adapter basterà richiamarlo, per esempio, in questo modo nell’azione del proprio controller:
if(Zend_Loader::isReadable('MyAuthAdapter.php')){
Zend_Loader::loadFile('MyAuthAdapter.php');
$authAdapter = new My_Auth_Adapter($username, $password, '3');
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
switch($result->getCode()) {
case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
$errorMessage = "Errore: Nome utente non corretto.";
break;
case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
$errorMessage = "Errore: Credenziali non valide.";
break;
case Zend_Auth_Result::SUCCESS:
$auth->getStorage()->write($username);
$this->_redirect('/admin');
break;
default:
$errorMessage = "Errore: Per accedere bisogna essere amministratori.";
break;
}
} else {
throw new Exception("MyAuthAdapter.php non esiste o è illeggibile.");
}
Per ulteriori informazioni rimando alla documentazione ufficiale di Zend Framework: http://framework.zend.com/manual/
Riferimenti utili:
http://framework.zend.com/manual/
http://www.openwall.com/phpass/
Esempio che mi ha aiutato a costruire il mio primo adapter
Tutorial: Getting Started with Zend Framework 1.8
Tutorial: Getting Started with Zend_Auth