Introduction to Zend_Auth
- Transfer
The article provides an overview of the features of the component
Author: Rob Alen, http://akrabat.com
Original: http://akrabat.com/zend-auth-tutorial
Translation: Alexander Musaev, http://paradigm.ru
Printable PDF: http: // archive .paradigm.ru / zend_auth.pdf
In the context of web applications, authentication usually means checking whether a user matches his account on a web server with a name (“login”) and password. As an example of the implementation of such a mechanism based on the Zend Framework, we will supplement the CD-ROM base with a similar check (the web application implemented in the article “Introduction to Zend Framework”).
For this we need:
When using MySQL, such a table can be created with the following query:
We will need to add a test user account to it:
Run these SQL queries using any MySQL client program. The username and password can be changed to any other values if desired.
We will need to make the following changes to the bootstrap file:
All you need to do here is to make sure the class is
In the constructor of the controller class, the view is initialized and the value of the variable is assigned
The login form is quite simple and contains only two fields - for the username and password.
The template displays
Now that our form is ready, we can move on to creating a controller to work with it.
To display the form, you need to specify its title and message body, after which the form can be seen by clicking on the URL
Consider the above code step by step:
Here, as usual, we extract the username and password from the POST array and process their values with an HTML filter. The function used for this
The authentication process continues only if the username is specified. If empty, an attempt to authenticate through
To work with authorization data
We must also pass to the adapter the exact values of the username and password that were entered into the form.
In order to perform the authentication procedure itself, a
In case the authentication was successful, the user account from the database will be completely saved inside the singleton
In the event that the verification of the username and password did not pass, we inform inform the user about this through a variable
The function
We will need to provide the user with a special link, by clicking on which he could exit the web application. The easiest way to do it is inside the template
It’s very convenient that it
Now we need to make changes to the file
Zend_Auth, which gives an overview of the implementation of user authorization in applications based on Zend Framework. As a basis for the given examples, the materials of the article "Introduction to Zend Framework" were used . Examples were tested on Zend Framework versions 0.9, 0.9.1 and 0.9.2, and most likely will work with later versions, but not with earlier ones. Author: Rob Alen, http://akrabat.com
Original: http://akrabat.com/zend-auth-tutorial
Translation: Alexander Musaev, http://paradigm.ru
Printable PDF: http: // archive .paradigm.ru / zend_auth.pdf
Before you start
The implementation of the user authentication mechanism, which we will use in our examples, is based on PHP sessions. Make sure that the session.save_path parameter in your isphp.iniset to the directory accessible to the web server for writing.Authentication
Authentication or authentication is the procedure for verifying the conformity of the subject and who he is trying to impersonate using some unique information. This procedure should be distinguished from identification (recognition of the subject of information interaction) and authorization (verification of access rights to system resources).In the context of web applications, authentication usually means checking whether a user matches his account on a web server with a name (“login”) and password. As an example of the implementation of such a mechanism based on the Zend Framework, we will supplement the CD-ROM base with a similar check (the web application implemented in the article “Introduction to Zend Framework”).
For this we need:
- create a table in the database for users (and add a new account to it);
- create a login form;
- implement a controller containing actions for entering and exiting;
- add the ability to log out to the general fragment of page templates;
- add verification that the user is logged in before allowing him to perform any action.
Users table
The first thing we need is a table in the database for storing user accounts. Her scheme will look like this:| Field | A type | Null? | Field options |
|---|---|---|---|
| id | Integer | No | Primary key, Autoincrement |
| username | Varchar (50) | No | Unique key |
| password | Varchar (50) | No | - |
| real_name | Varchar (100) | No | - |
When using MySQL, such a table can be created with the following query:
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)
)We will need to add a test user account to it:
INSERT INTO users (id, username, password, real_name)
VALUES (1, 'rob', 'rob', 'Rob Allen');Run these SQL queries using any MySQL client program. The username and password can be changed to any other values if desired.
Boot file
In order to be able to track the registration of users in the system (entry and exit), we need to use the mechanism of PHP-sessions. For convenient work with it, the Zend Framework provides a special classZend_Session_Namespace. We will need to make the following changes to the bootstrap file:
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();
...All you need to do here is to make sure the class is
Zend_Authconnected and the database adapter is dbAdapterregistered. This adapter will be stored in the registry, because later you will need to have access to it from the authorization controller.Authorization controller
In order to group the input and output actions, we need a special controller. It would be logical to ask him a nameAuthController. Let's start its implementation with the constructor and define the default action ( indexAction()):zf-tutorial/application/controllers/AuthController.php:
class AuthController extends Zend_Controller_Action
{
function init()
{
$this->initView();
$this->view->baseUrl = $this->_request->getBaseUrl();
}
function indexAction()
{
$this->_redirect('/');
}
}In the constructor of the controller class, the view is initialized and the value of the variable is assigned
baseUrl. In addition to the constructor, an action is defined in the class indexAction(), which is a mandatory requirement for all heirs Zend_Controller_Action. Given that we are going to use only loginAction()and logoutAction(), we don’t need a default action, therefore we will redirect the user from the corresponding URL to the main page of the site.entrance
In order to enter the system, you need a special form. Alogincontroller action AuthControllerwill interact with it in the same way that actions IndexControllerwork with their forms. The form template is located in the file views/scripts/auth/login.phtml, and the data from it will be processed by the method AuthController::loginAction(). The login form is quite simple and contains only two fields - for the username and password.
zf-tutorial/application/views/scripts/auth/login.phtml:render('header.phtml'); ?>
escape($this->title); ?>
message)) :?>
escape($this->message);?>
render('footer.phtml'); ?>The template displays
header.phtmlboth footer.phtmlat the beginning and at the end of the page, respectively. Note that a message from a variable $this→messageis displayed only if its value is not empty. This variable is used if there were errors during the login and the user needs to report it. The rest of the template is the login form itself. Now that our form is ready, we can move on to creating a controller to work with it.
zf-tutorial/application/controllers/AuthController.php:class AuthController extends Zend_Controller_Action
{
...
function loginAction()
{
$this->view->message = '';
$this->view->title = "Log in";
$this->render();
}
}To display the form, you need to specify its title and message body, after which the form can be seen by clicking on the URL
http://zf-tutorial/auth/login. The question arises, how, in this case, 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 entries to IndexController. That is, data processing will be performed only if the method of accessing the server is POST. Otherwise, the action loginwill simply produce a form. The necessary changes 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();
}
}Consider the above code step by step:
// 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 {
...Here, as usual, we extract the username and password from the POST array and process their values with an HTML filter. The function used for this
getPost()automatically checks for the presence of variables specified in its parameter and, if none are found in POST, returns an empty value. The authentication process continues only if the username is specified. If empty, an attempt to authenticate through
Zend_Authwould raise 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');To work with authorization data
Zend_Auth, the adapter subsystem is used. Such adapters provide a unified interface to heterogeneous data stores, such as relational databases, LDAP, or simple files. In our example, the database will be used for this purpose, so the adapter is selected Zend_Auth_Adapter_DbTable. In order to initialize it, it is necessary to set 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);We must also pass to the adapter the exact values of the username and password that were entered into the form.
// do the authentication
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);In order to perform the authentication procedure itself, a
authenticate()class method is called Zend_Auth. In this case, the authentication result 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('/');In case the authentication was successful, the user account from the database will be completely saved inside the singleton
Zend_Auth(with the exception of the password, of course). } else {
// failure: clear database row from session
$this->view->message = 'Login failed.';
}
}In the event that the verification of the username and password did not pass, we inform inform the user about this through a variable
message. This completes the authentication process for logging in.Exit
Logging out is much easier than logging in. All that is required is to clear the data inside the singletonZend_Auth. This is implemented in the action of the logoutAction()controller AuthController. Thus, to exit, you just need to go to the URL http://zftutorial/auth/logout.zf-tutorial/application/controllers/AuthController.php:class AuthController extends Zend_Controller_Action
{
...
function logoutAction()
{
Zend_Auth::getInstance()->clearIdentity();
$this->_redirect('/');
}
}The function
logoutAction()is so trivial that there is absolutely nothing to comment on. We will need to provide the user with a special link, by clicking on which he could exit the web application. The easiest way to do it is inside the template
footer. In addition, we will tell the user his name so that he is sure that the authorization was successful. User names are stored in the field of the real_namecorresponding database table, and can be accessed from Zend_Auth. The first thing that needs to be done is to pass this value into a view, which we will do inside the init()controller function IndexController().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();
}
...
}It’s very convenient that it
Zend_Authis singleton. Otherwise, in this case, it would be necessary to store its contents in the registry. Now we need to make changes to the file
footer.phtml.zf-tutorial/application/views/footer.phtml:user) : ?>
Logged in as
echo $this->escape($this->user->real_name);?>.
Logout
The above code does not contain anything fundamentally new. We use
escape()to make sure that the username is displayed correctly in the browser. The value of the variable baseUrlis used to correctly form the link. The logout function is ready.
Action protection
All that remains for us to do is to make sure that no actions will be unavailable before the user logs in.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');
}
}
...
}A function with a standard name is
preDispatch()automatically called before any action by the controller. Using the hasIdentity()object method Zend_Auth, we check to see if the login is complete. And, if it’s not, redirect the user to auth/login. This completes the work on authorization.
Conclusion
The given example of the implementation of user authorization functions based on the Zend Framework is quite simple, but you should understand thatZend_Auththere are many more useful features that can be used to protect more complex applications with several controllers. The authorization system implemented in the component was also not affected Zend_Acl. The latter is intended to be used in conjunction with Zend_Authto delimit the levels of user access to actions or data, but this is already a topic for another discussion. You can send all comments regarding the original article to the author at rob@akrabat.com. Comments on the Russian translation send to musayev@yandex.ru.
Update: an archive with examples of programs from the article can be found on the author’s website:zend_auth-tutorial_104.zip .