Zend_Auth
component, giving a general idea of the implementation of user authorization in applications based on the Zend Framework. As a basis for the examples given, we used materials from the article “Introduction to the Zend Framework” . The examples are tested on the Zend Framework versions 0.9, 0.9.1 and 0.9.2, and most likely will work with later versions, but not earlier ones. php.ini
set to the directory that the web server can write to.Field | Type of | Null? | Field options |
---|---|---|---|
id | Integer | No | Primary key, Autoincrement |
username | Varchar (50) | No | Unique key |
password | Varchar (50) | No | - |
real_name | Varchar (100) | No | - |
CREATE TABLE users (
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL,
real_name VARCHAR(100) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY username (username)
)
INSERT INTO users (id, username, password, real_name)
VALUES (1, 'rob', 'rob', 'Rob Allen');
Zend_Session_Namespace
provided in the Zend Framework.zf-tutorial/index.php:
...
Zend_Loader::loadClass('Zend_Db_Table');
Zend_Loader::loadClass('Zend_Debug');
Zend_Loader::loadClass('Zend_Auth');
// load configuration
...
// setup database
$dbAdapter = Zend_Db::factory($config->db->adapter,
$config->db->config->asArray());
Zend_Db_Table::setDefaultAdapter($dbAdapter);
Zend_Registry::set('dbAdapter', $dbAdapter);
// setup controller
$frontController = Zend_Controller_Front::getInstance();
...
Zend_Auth
class Zend_Auth
connected and the dbAdapter
database dbAdapter
registered. This adapter will be stored in the registry, because later you will need to have access to it from the authorization controller.AuthController
. Let's start its implementation with the constructor and define the default action ( indexAction()
):zf-tutorial/application/controllers/AuthController.php:
<?php
class AuthController extends Zend_Controller_Action
{
function init()
{
$this->initView();
$this->view->baseUrl = $this->_request->getBaseUrl();
}
function indexAction()
{
$this->_redirect('/');
}
}
baseUrl
variable is baseUrl
. In addition to the constructor, the class defines an indexAction()
action, which is a mandatory requirement for all heirs to Zend_Controller_Action
. Considering that we are going to use only loginAction()
and logoutAction()
, we will not need the default action, so we will redirect the user from the corresponding URL to the home page of the site.login
action of the AuthController
controller will interact with it in the same way as the IndexController
actions work with their forms. The form template is located in the views/scripts/auth/login.phtml
, and the data from it will be processed by the AuthController::loginAction()
method.zf-tutorial/application/views/scripts/auth/login.phtml:
<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php if(!empty($this->message)) :?>
<div id="message">
<?php echo $this->escape($this->message);?>
</div>
<?php endif; ?>
<form action="<?php echo $this->baseUrl ?>/auth/login" method="post">
<div>
<label for="username">Username</label>
<input type="text" name="username" value=""/>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" value=""/>
</div>
<div id="formbutton">
<input type="submit" name="login" value="Login" />
</div>
</form>
<?php echo $this->render('footer.phtml'); ?>
header.phtml
and footer.phtml
at the beginning and at the end of the page, respectively. Note that the message from the $this→message
variable is displayed only when its value is not empty. This variable is used if an error has occurred at the entrance and the user needs to report it. The rest of the template is the login form itself.zf-tutorial/application/controllers/AuthController.php:
class AuthController extends Zend_Controller_Action
{
...
function loginAction()
{
$this->view->message = '';
$this->view->title = "Log in";
$this->render();
}
}
http://zf-tutorial/auth/login
http://zf-tutorial/auth/login
. The question arises how, in this case, to process the data sent from it? To do this, we use the same method that was used in the case of forms for editing and adding records to the IndexController
. That is, data processing will be performed only if the method of accessing the server is POST. Otherwise, the login
action will simply issue the form. The necessary changes to loginAction()
are shown below.zf-tutorial/application/controllers/AuthController.php:
class AuthController extends Zend_Controller_Action
{
...
function loginAction()
{
$this->view->message = '';
if ($this->_request->isPost()) {
// collect the data from the user
Zend_Loader::loadClass('Zend_Filter_StripTags');
$f = new Zend_Filter_StripTags();
$username = $f->filter($this->_request->getPost('username'));
$password = $f->filter($this->_request->
getPost('password'));
if (empty($username)) {
$this->view->message = 'Please provide a username.';
} else {
// setup Zend_Auth adapter for a database table
Zend_Loader::loadClass('Zend_Auth_Adapter_DbTable');
$dbAdapter = Zend_Registry::get('dbAdapter');
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('users');
$authAdapter->setIdentityColumn('username');
$authAdapter->setCredentialColumn('password');
// Set the input credential values
// to authenticate against
$authAdapter->setIdentity($username);
$authAdapter->setCredential($password);
// do the authentication
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
// success: store database row to auth's storage
// system. (Not the password though!)
$data = $authAdapter->getResultRowObject(null, 'password');
$auth->getStorage()->write($data);
$this->_redirect('/');
} else {
// failure: clear database row from session
$this->view->message = 'Login failed.';
}
}
}
$this->view->title = "Log in";
$this->render();
}
}
// collect the data from the user
Zend_Loader::loadClass('Zend_Filter_StripTags');
$f = new Zend_Filter_StripTags();
$username = $f->filter($this->_request->getPost('username'));
$password = $f->filter($this->_request->getPost('password'));
if (empty($username)) {
$this->view->message = 'Please provide a username.';
} else {
...
getPost()
function used in this case automatically checks for the presence of variables set in its parameter and, if not found in POST, returns an empty value.Zend_Auth
would Zend_Auth
an exception.// setup Zend_Auth adapter for a database table
Zend_Loader::loadClass('Zend_Auth_Adapter_DbTable');
$dbAdapter = Zend_Registry::get('dbAdapter');
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
$authAdapter->setTableName('users');
$authAdapter->setIdentityColumn('username');
$authAdapter->setCredentialColumn('password');
Zend_Auth
, the adapter subsystem is used. Such adapters provide a unified interface to diverse data stores, such as relational databases, LDAP, or simple files. In our example, a database will be used for this purpose, therefore the adapter Zend_Auth_Adapter_DbTable
selected. In order to initialize it, you must specify the database parameters (the name of the user table and the names of its fields).// Set the input credential values to authenticate against
$authAdapter->setIdentity($username);
$authAdapter->setCredential($password);
// do the authentication
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
Zend_Auth
class authenticate()
method is called. At the same time, the result of authentication is automatically saved in the session.if ($result->isValid()) {
// success : store database row to auth's storage
// system. (not the password though!)
$data = $authAdapter->getResultRowObject(null,
'password');
$auth->getStorage()->write($data);
$this->_redirect('/');
Zend_Auth
singleton (with the exception of the password, of course).} else {
// failure: clear database row from session
$this->view->message = 'Login failed.';
}
}
message
variable. This completes the login process for authentication.Zend_Auth
singleton. This is implemented in the logoutAction()
action of the logoutAction()
controller. Thus, to exit you just need to go to the URL http://zftutorial/auth/logout
http://zftutorial/auth/logout
.zf-tutorial/application/controllers/AuthController.php:
class AuthController extends Zend_Controller_Action
{
...
function logoutAction()
{
Zend_Auth::getInstance()->clearIdentity();
$this->_redirect('/');
}
}
logoutAction()
function is so trivial that there’s absolutely nothing to comment on.footer
template. In addition, we will inform the user of his name, in order to make sure that the authorization was successful. User names are stored in the real_name
field of the corresponding database table, and can be accessed from Zend_Auth
. The first thing you need to do is pass this value into view, which we will do inside the init()
function of the IndexController()
controller.zf-tutorial/application/controllers/IndexController.php:
class IndexController extends Zend_Controller_Action
{
function init()
{
$this->initView();
Zend_Loader::loadClass('Album');
$this->view->baseUrl = $this->_request->getBaseUrl();
$this->view->user = Zend_Auth::getInstance()->getIdentity();
}
...
}
Zend_Auth
is a singleton. Otherwise, in this case, it would be necessary to store its contents in the registry.footer.phtml
file.zf-tutorial/application/views/footer.phtml:
<?php if($this->user) : ?>
<p id="logged-in">Logged in as <?php
echo $this->escape($this->user->real_name);?>.
<a href="<?php echo $this->baseUrl ?>/auth/logout">Logout</a></p>
<?php endif; ?>
</div>
</body>
</html>
escape()
to make sure that the username is correctly displayed in the browser. The value of the baseUrl
variable baseUrl
used to correctly form the link.zf-tutorial/application/controllers/IndexController.php:
class IndexController extends Zend_Controller_Action
{
...
function preDispatch()
{
$auth = Zend_Auth::getInstance();
if (!$auth->hasIdentity()) {
$this->_redirect('auth/login');
}
}
...
}
preDispatch()
automatically called before any controller action. Using the hasIdentity()
method of the hasIdentity()
object, we check whether the login is done. And, if this is not the case, we redirect the user to auth/login
.Zend_Auth
still has many useful features that you can use to protect more complex applications with multiple controllers. The authorization system implemented in the Zend_Acl
component was not affected as well. The latter is designed to be used in conjunction with Zend_Auth
to differentiate the levels of user access to actions or data, but this is a topic for a separate conversation.Source: https://habr.com/ru/post/31178/
All Articles