Programmer's Reference Guide

Managing User Sessions In ZF

Authenticating Users in Zend Framework

Introduction to Authentication

Once a web application has been able to distinguish one user from another by establishing a session, web applications typically want to validate the identity of a user. The process of validating a consumer as being authentic is "authentication." Authentication is made up of two distinctive parts: an identity and a set of credentials. It takes some variation of both presented to the application for processing so that it may authenticate a user.

While the most common pattern of authentication revolves around usernames and passwords, it should be stated that this is not always the case. Identities are not limited to usernames. In fact, any public identifier can be used: an assigned number, social security number, or residence address. Likewise, credentials are not limited to passwords. Credentials can come in the form of protected private information: fingerprint, eye retinal scan, passphrase, or any other obscure personal information.

Basic Usage of Zend_Auth

In the following example, we will be using Zend_Auth to complete what is probably the most prolific form of authentication: username and password from a database table. This example assumes that you have already setup your application using Zend_Application, and that inside that application you have configured a database connection.

The job of the Zend_Auth class is twofold. First, it should be able to accept an authentication adapter to use to authenticate a user. Secondly, after a successful authentication of a user, it should persist throughout each and every request that might need to know if the current user has indeed been authenticated. To persist this data, Zend_Auth consumes Zend_Session_Namespace, but you will generally never need to interact with this session object.

Lets assume we have the following database table setup:

  1. CREATE TABLE users (
  2.     id INTEGER  NOT NULL PRIMARY KEY,
  3.     username VARCHAR(50) UNIQUE NOT NULL,
  4.     password VARCHAR(32) NULL,
  5.     password_salt VARCHAR(32) NULL,
  6.     real_name VARCHAR(150) NULL
  7. )

The above demonstrates a user table that includes a username, password, and also a password salt column. This salt column is used as part of a technique called salting that would improve the security of your database of information against brute force attacks targeting the algorithm of your password hashing. » More information on salting.

For this implementation, we must first make a simple form that we can utilized as the "login form". We will use Zend_Form to accomplish this.

  1. // located at application/forms/Auth/Login.php
  2.  
  3. class Default_Form_Auth_Login extends Zend_Form
  4. {
  5.     public function init()
  6.     {
  7.         $this->setMethod('post');
  8.  
  9.         $this->addElement(
  10.             'text', 'username', array(
  11.                 'label' => 'Username:',
  12.                 'required' => true,
  13.                 'filters'    => array('StringTrim'),
  14.             ));
  15.  
  16.         $this->addElement('password', 'password', array(
  17.             'label' => 'Password:',
  18.             'required' => true,
  19.             ));
  20.  
  21.         $this->addElement('submit', 'submit', array(
  22.             'ignore'   => true,
  23.             'label'    => 'Login',
  24.             ));
  25.  
  26.     }
  27. }

With the above form, we can now go about creating our login action for our authentication controller. This controller will be called "AuthController", and will be located at application/controllers/AuthController.php. It will have a single method called " loginAction()" which will serve as the self-posting action. In other words, regardless of the url was POSTed to or GETed to, this method will handle the logic.

The following code will demonstrate how to construct the proper adapter, integrate it with the form:

  1. class AuthController extends Zend_Controller_Action
  2. {
  3.  
  4.     public function loginAction()
  5.     {
  6.         $db = $this->_getParam('db');
  7.  
  8.         $loginForm = new Default_Form_Auth_Login();
  9.  
  10.         if ($loginForm->isValid($_POST)) {
  11.  
  12.             $adapter = new Zend_Auth_Adapter_DbTable(
  13.                 $db,
  14.                 'users',
  15.                 'username',
  16.                 'password',
  17.                 'MD5(CONCAT(?, password_salt))'
  18.                 );
  19.  
  20.             $adapter->setIdentity($loginForm->getValue('username'));
  21.             $adapter->setCredential($loginForm->getValue('password'));
  22.  
  23.             $auth   = Zend_Auth::getInstance();
  24.             $result = $auth->authenticate($adapter);
  25.  
  26.             if ($result->isValid()) {
  27.                 $this->_helper->FlashMessenger('Successful Login');
  28.                 $this->_redirect('/');
  29.                 return;
  30.             }
  31.  
  32.         }
  33.  
  34.         $this->view->loginForm = $loginForm;
  35.  
  36.     }
  37.  
  38. }

The corresponding view script is quite simple for this action. It will set the current url since this form is self processing, and it will display the form. This view script is located at application/views/scripts/auth/login.phtml:

  1. $this->form->setAction($this->url());
  2. echo $this->form;

There you have it. With these basics you can expand the general concepts to include more complex authentication scenarios. For more information on other Zend_Auth adapters, have a look in the reference guide.


Managing User Sessions In ZF

Comments

You called:
$result = $auth->autenticate($adapter);
But from where comes '$auth'? You're calling a method from an uncreated object. Could you explain?
You can get an instance of Zend_Auth by calling the static method getInstance :

$auth = Zend_Auth::getInstance();
$result = $auth->autenticate($adapter);


But since Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface, the following should work :

$result = $adapter->authenticate();
Forget about :

But since Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface, the following should work :

$result = $adapter->authenticate();

Hi, I am new to zend and php and having a problem setting auth. When I fill in my login info I am getting an error message and this is what is showing in my apache error log :

PHP Warning: htmlspecialchars()
imo it would be more plain, if the form would be called as "$this->loginForm" in the view, wouldn't it?
$this->redirect('/');

didn't work for me, but

$this->_helper->redirector('index','index');

worked fine, like described in that old, but helfull, tutorial of Matthew Weier O'Phinney
http://weierophinney.net/matthew/archives/165-Login-and-Authentication-with-Zend-Framework.html
Use:

$this->_redirect('/');
When i ma tryin using the function
$db = $this->_getParam('db');
var_dump($db);
i am getting null please suggest me what is the problem is
Hi
I am working on user authentication
i am using the following code
public function loginAction()
{
$db = $this->_getParam('db');
var_dump($db);

$users = new Application_Model_User();
$form = new Application_Form_Loginform();
$this->view->form = $form;

if($this->getRequest()->isPost())
{

## first if start ##
if($form->isValid($_POST))
{
$data = $form->getValues();

$adapter = new Zend_Auth_Adapter_DbTable(

$db,

'users',

'root',

'',

'MD5(CONCAT(?, password_salt))'

);



$adapter->setIdentity($form->getValue('username'));

$adapter->setCredential($form->getValue('password'));



$result = $auth->authenticate($adapter);

if($result->isValid()){
$storage = new Zend_Auth_Storage_Session();
$storage->write($authAdapter->getResultRowObject());
$this->_redirect('auth/home');
}else
{
$this->view->errorMessage = "Invalid username or password. Please try again.";
}
## second if close ##

}
## first if close ##

}
}


I am using zend v 1.10
i am getting following error

Catchable fatal error: Argument 1 passed to Zend_Auth_Adapter_DbTable::__construct() must be an instance of Zend_Db_Adapter_Abstract, null given, called in C:\wamp\www\zfpage2\application\controllers\IndexController.php on line 59 and defined in C:\wamp\www\zfpage2\library\Zend\Auth\Adapter\DbTable.php on line 128
This $this->form should be $this->loginForm;
This example code is full of errors.

I have to debug for 15 minutes to make it working.
(I have several years PHP experience)

However, I learned the concepts and applied to what I already knew on Zend Framework. ZF is very versatile. Thanks for the tutorial.

For others who struggles with the code examples, you have to change the directory name and form class name in the to fit the ZF MVC nameing convention.
To name a few errors:
you need to correct the $loginForm->isVaild to $loginForm->isVaild($POST)
And on the view page,correct $this->form to $this->loginForm;

Hope it helps.
I had quite a bit of difficulty with this one.
These tutorials are something to be desired.

First off I'm using a mysql database. so rather than this:

$db = $this->_getParam('db');

$loginForm = new Default_Form_Auth_Login($_POST);

I used this:


$config = new Zend_Config_Ini(APPLICATION_PATH. '/configs/application.ini', 'production');

$db = new Zend_Db_Adapter_Pdo_MySql(array(
'adapter'=>$config->resources->db->adapter,
'host'=>$config->resources->db->params->host,
'username'=>$config->resources->db->params->username,
'password'=>$config->resources->db->params->password,
'dbname'=> $config->resources->db->params->dbname));


Along with all the other errors like:



if ($loginForm->isValid($_POST)) {

$result = $adapter->authenticate();

$this->_helper->redirector('index','index');

Login.php

<?php
$this->loginForm->setAction($this->url());
echo $this->loginForm;


and I had to change the name of the Login form and class to match directory structure

Application_Form_Auth_Login
$loginForm = new Application_Form_Login();
if ($loginForm->isValid($this->getRequest()->getPost()))


$result = $adapter->authenticate();


$this->_helper->redirector('index');
This tutorial is woefully inadequate.

I expect to have to work to understand concepts and perhaps read around a bit to understand related elements, but there really are too many assumptions made here, that make the learning process much more difficult than it need be.
I've probably spent about 3 hours trying to understand this and got to the point where the form renders and connects to the database however its not validating correctly yet.
It has forced me to understand a few more of the related issues, but I think with a better explanation, this could have been achieved a little quicker.
The bits that needed changing on my system were:

class Default_Form_Auth_Login extends Zend_Form
should be
class [b]Application[/b]_Form_Auth_Login extends Zend_Form

and
$this->form->setAction($this->url());
echo $this->form;
should be
$this->[b]loginForm[/b]->setAction($this->url());
echo $this->[b]loginForm[/b];
Lot of comments correcting the code, then why is the original code still NOT corrected? Lot of people have spent time to comment on the correct it?

It is more time consuming to read all the comments and then get your code working.

Regards,
Shashidhar.G
So... this is a great start for logining a user in. But What do you use to make sure a user is logged in and if not redirect them to the login form?

If/When I figure it out, I'll post it here since it's doubtful the author will.
In order to find out wether a user has logged in already or not just use the method
$auth->hasIdentity() like in

if( !$auth->hasIdentity() )
{
$this->_redirect("login");
}

On the other hand if you want to check that in every page in your site, you might consider writing a plugin.

+ Add A Comment

Please do not report issues via comments; use the ZF Issue Tracker.

If you have a JIRA/Crowd account, we suggest you login first before commenting.

  • BBCode is allowed in the comment markup

  • Select a Version

    Languages Available

    Components

    Search the Manual