Authorization using Zend_Auth
In this article we will consider usage of one of the Zend Framework components as usual, except for a small deviation from the plan: up to this point there was an archive with the source code of the demo application (this is what was made in result by working with components) which was attached to each article filled under "Developing applications using ZF" heading (i mean russian version of the site). It will not be done that way now - we will consider components separately from each other, because, as it turned out, within the bounds of 2Developers it's been needed to a little of people. Concerning Zend Framework CMS I should say that we started an open project of its development, so details will be covered later in the following articles.
Thus, authorization using Zend_Auth, "remember me" feature and initialization of a session length (time pending which a user is logged in) will be considered.
Users table
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`login` varchar(36) NOT NULL,
`pass` varchar(36) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `login` (`login`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Controller
Let's add 2 actions in the controller. For instance, UserController:
<?php
require_once 'Zend/Controller/Action.php';
class UserController extends Zend_Controller_Action
{
public function loginAction()
{
// If data was sent
if(isset($_POST['login']) && !empty($_POST['login'])) {
// Connect to the database and receive the adapter
require_once 'Zend/Db.php';
$db_adapter = Zend_Db::factory('pdo_mysql',
array('host' => 'localhost',
'username' => 'test',
'password' => 'test',
'dbname' => 'test'
)
);
// Receive the model
require_once(APPPATH."/models/User.php");
$user_model = new User($db_adapter);
if (true === $message = $user_model->login($_POST['login'], $_POST['pass'])) {
// Successfully
$this->_redirect('/');
} else {
$this->view->assign('errors', $message);
}
}
}
//__________________________________________________________
public function logoutAction()
{
// Shutdown view script and layout
$this->_helper->viewRenderer->setNoRender(true);
Zend_Layout::getMvcInstance()->disableLayout();
require_once 'Zend/Auth.php';
$auth = Zend_Auth::getInstance();
// Delete the information from the session
$auth->clearIdentity();
Zend_Session::forgetMe();
$this->_redirect('/');
}
//__________________________________________________________
As you could notice, principal action and operation with Zend_Auth component is held in a model. Therein we will just get the result if all is passed successfully, than a model will return true. Otherwise, we will get the error message.
Model.
<?php
require_once 'Zend/Db/Table/Abstract.php';
class User extends Zend_Db_Table_Abstract
{
protected $_name = 'users';
protected $_primary = array('login');
public function login($login, $pass)
{
require_once 'Zend/Auth.php';
// Receive Zend_Auth instance
$auth = Zend_Auth::getInstance();
require_once 'Zend/Auth/Adapter/DbTable.php';
// Create Adapter for Zend_Auth, indication where in the database
//it should search for login and password for comparison
$authAdapter = new Zend_Auth_Adapter_DbTable($this->getAdapter(), 'users', 'login', 'pass', "MD5(?)");
$authAdapter->setIdentity($login)
->setCredential($pass);
// Checks and saves the result of authentication
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
// Successfully
// It's possible to save the session in additional fields
$auth->getStorage()->write($authAdapter->getResultRowObject(array('id', 'login')));
// Receive Zend_Session_Namespace object
require_once('Zend/Session/Namespace.php');
$session = new Zend_Session_Namespace('Zend_Auth');
// Set the time of user logged in
$session->setExpirationSeconds(24*3600);
// If "remember" was marked
if (isset($_POST['rememberme'])) {
Zend_Session::rememberMe();
}
return true;
}
// Abortive
return $error_msg = $result->getMessages();
}
}
Here are several moments not described in ZF manual, that should be addressed.
Firstly, usage of the fourth parameter while getting the Auth of adapter is the feature which is applied to the password. It's possible to add some salt, but in general the password can be stored abroach so the parameter wouldn't be transfered. Most probably you will not act like this ;)
Secondly, time when the session is active is often necessary to be more than 15 minutes by default.
Thirdly, "remember me" feature stores cookies in a client's browser.
View script
<form action="<?php echo $this->url(); ?>" method="post">
<fieldset>
<legend>Sign in</legend>
<?php if (sizeof($this->errors)) echo $this->formErrors($this->errors).'<br />'; // Error output (by the way of bulleted list)?>
<label for="login">Login</label>
<input type="text" id="login" name="login" value="<?php if (isset($_POST['login'])) echo $_POST['login'];?>" />
<br /><br />
<label for="pass">Password</label>
<input type="password" id="pass" name="pass" value="<?php if (isset($_POST['pass'])) echo $_POST['pass'];?>" />
<br /><br />
<label for="rememberme">Remember me</label>
<input type="checkbox" id="rememberme" name="rememberme" value="1" />
<br /><br />
<input type="submit" value="Submit" />
<br /><br />
</fieldset>
</form>
Seems like it's over for general usage.
Comments
Agree, storing some hashes in db and cookie is required, then matching, maybe ip should be invoilved as well.
hi
please help me
when i click on the submit the page is clear and show only ' / ' .
table user create and enter data.but show only / .
please help me
tanks
What are the filenames and paths of the files you mention above?
hi
why in the Model. file the line
mehdi,
Like the brevity of the article but a couple of points:
You are not escaping user input when redisplaying the form.
You might also end up displaying authentication errors - I think that's a bad idea. Better to display a generic 'FAIL TRY AGAIN' message.
Placing the login method in a db table object doesn't make much sense to me.
Where is the code to determine if the user is already logged in. I mean, suppose a use logged in and set the option of remember me. Then if he comes to login page, he should be automatically redirected to the home page of the site, Right? there should be code at the beginning to check if the session ID is already stored in the cookie.If so, he should be logged in automatically. Anyways, Its a nice tute.
Regards,
And thanks.