Ich habe versucht, ein Login-Widget zu erstellen, das in jeder Aktion enthalten sein kann, die außerhalb des Inhalts der Anwendung ist, die Anmeldung erfordert. Mein Gedanke hier war, dass ich einen DRY-Ansatz wünschte, um die Login-Box mit allen Fehlermeldungen eines vorherigen Anmeldeversuchs zu rendern. Um dies zu aktivieren, habe ich die FlashMessenger zum Speichern des Ergebnisses eines fehlgeschlagenen Anmeldeversuchs verwendet. Das Widget verwendet auch die Post/Redirect/Get-pattern, um das Problem zu vermeiden, Daten mehrfach zu posten, wenn Sie die Zurück-Schaltfläche des Browsers verwenden.Refactoring eines Zend_View_Helper_Action Widget mit Zend_Controller_Action_Helper_FlashMessenger, in ein Modell
Nun, das Problem ist, dass ich lieber nicht die Zend_View_Helper_Action verwenden würde, da dieser Helfer die Anfrage klont und einen weiteren Lauf der Dispatch-Schleife erstellt, die ziemlich ressourcenintensiv ist. Also, indem Sie auf den Code suchen, könnten Sie mir einen Rat geben, wie man den Code Refactoring, so dass:
- Das Widget kann in einer beliebigen Ansicht Skript
- Ergebnisse aus einer früheren aufgenommen werden Anmeldeversuch gemacht wird
- das Widget nicht einen Lauf in der Dispatch-Schleife aufrufen
Derzeit ist die Login-Widget ist durch den Aufruf, in den View Skripten gemacht:
echo $this->action('auth', 'login-widget');
AuthController.php:
class AuthController extends Zend_Controller_Action {
// This method is invoked by Zend_View_Helper_Action to render the
// login widget
public function loginWidgetAction() {
$flashMessenger = $this->_helper->flashMessenger->setNamespace('login');
$this->view->messages = $flashMessenger->getMessages();
}
public function loginAction() {
if($this->getRequest()->isPost()) {
$result = Auth::doLogin($this->getRequest()->getPost());
if($result->isValid()) {
$this->_redirect('user');
}
else {
$flashMessenger = $this->_helper->flashMessenger->
setNamespace('login');
foreach($result->getMessages() as $message) {
$flashMessenger->addMessage($message);
}
}
}
// This will be changed to redirect either to the index page,
// or the page the request originated from if available.
$this->_redirect('');
}
[...]
}
/models/Auth.php:
/**
* Model for encapsulating the actions that deals with authentication,
* such as registering and activating users, as well as logging in and
* logging out.
* @todo: Refactor this to remove static methods
*/
class Auth {
/**
*
* @return Zend_Auth_Result
*/
public static function doLogin ($credentials) {
$authAdapter = new Auth_Adapter_DbTable(
Zend_Db_Table::getDefaultAdapter(),
'Users',
'username',
'pwdHash',
'SHA1(CONCAT(?, salt))'
);
$authAdapter->setIdentity($credentials['username']);
$authAdapter->setCredential($credentials['password']);
$auth = Zend_Auth::getInstance();
return $auth->authenticate($authAdapter);
}
[...]
}
/models/Auth/Adapter/DbTable. php:
class Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable {
/**
* authenticate() - defined by Zend_Auth_Adapter_Interface. This method
* is called to attempt an authenication. 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
* @see library/Zend/Auth/Adapter/Zend_Auth_Adapter_DbTable#authenticate()
* @return MedU_Auth_Result
*/
public function authenticate() {
return parent::authenticate();
}
/**
* _authenticateValidateResult() - This method attempts to validate that
* the record in the result set is indeed a record that matched the
* identity provided to this adapter.
*
* Additionally it checks that the user account is activated.
*
* @param array $resultIdentity
* @return MedU_Auth_Result
*/
protected function _authenticateValidateResult($resultIdentity)
{
$result = parent::_authenticateValidateResult($resultIdentity);
if(!$result->isValid()) { return $result; }
$this->_checkAccountIsActivated($resultIdentity);
$this->_checkAccountIsSuspended($resultIdentity);
// Overwrite the username supplied by the user and instead
// use the name supplied upon registration, i.e if the
// user signs in as uSERNAME and registered as Username,
// the identity is Username
$this->_authenticateResultInfo['identity'] =
$resultIdentity[$this->_identityColumn];
return $this->_authenticateCreateAuthResult();
}
protected function _checkAccountIsActivated ($resultIdentity) {
if(!$resultIdentity['activated']) {
$this->_authenticateResultInfo['code'] =
MedU_Auth_Result::FAILURE_NOT_ACTIVATED;
$this->_authenticateResultInfo['messages'] =
array('The account has not yet been activated.
Please click on the link provided in the
activation email.');
}
}
protected function _checkAccountIsSuspended ($resultIdentity) {
if($resultIdentity['suspended']) {
$this->_authenticateResultInfo['code'] =
MedU_Auth_Result::FAILURE_SUSPENDED;
$this->_authenticateResultInfo['messages'] =
array('The account has been suspended.
If you feel this is a mistake,
please contact our support: [email protected]');
}
}
/**
* _authenticateCreateAuthResult() - This method creates a
* MedU_Auth_Result object from the information that has
* been collected during the authenticate() attempt.
*
* @return MedU_Auth_Result
*/
protected function _authenticateCreateAuthResult()
{
return new MedU_Auth_Result(
$this->_authenticateResultInfo['code'],
$this->_authenticateResultInfo['identity'],
$this->_authenticateResultInfo['messages']
);
}
}
/ansichten/scripts/auth/partials/logi n-widget.phtml
// The fetchForm-view helper returns a Zend_Form object.
// The form definition (xml) is attached below in the
// code box below this one.
<div class="box">
<h3>Login</h3>
<?php if($this->messages) : ?>
<ul class="errors">
<?php foreach($this->messages as $message) : ?>
<li><?php echo $message ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<div>
<?php echo $this->fetchForm('user', 'login') ?>
</div>
</div>
/application/configs/forms.xml
// Configuration of the Login form. 'user' and 'login' are
// just keys for the view helper to return the correct form
<forms>
<user>
<login>
<action value="/auth/login" />
<method value="post" />
<elements>
<username>
<type value="text"></type>
<options>
<label value="Username" />
<required value="true" />
<validators>
<alnum validator="alnum" />
<strlen validator="StringLength">
<options min="6" max="45" />
</strlen>
</validators>
</options>
</username>
<password>
<type value="password" />
<options>
<label value="Password" />
<required value="true" />
<validators>
<strlen validator="StringLength">
<options min="6" max="20" />
</strlen>
</validators>
</options>
</password>
<submit>
<type value="submit" />
<options>
<label value="Log in" />
</options>
</submit>
</elements>
</login>
+1, Interessante Frage, aber warum sollte man nicht eine einfache Umleitung ausgeben, um, sagen wir, AuthController-> loginaction, wenn ein nicht eingeloggten versucht der Benutzer, auf geschützte Inhalte zuzugreifen? Gibt es einen besonderen Grund? – karim79
Natürlich muss ich das noch tun, aber ich möchte dem Benutzer die Möglichkeit geben, sich einzuloggen, wenn er Lust dazu hat, ohne ihn dazu zu zwingen, zuerst auf einen Link zu klicken, der eine Anmeldung erfordert. Zum Beispiel, um eine Login-Box in einer Seitenleiste zu haben, wenn der Benutzer nicht eingeloggt ist. – PatrikAkerstrand