Zend_Auth
provides an API for authentication and
includes concrete authentication adapters for common use case scenarios.
Zend_Auth
is concerned only with authentication
and not with authorization. Authentication is loosely defined as
determining whether an entity actually is what it purports to be (i.e., identification),
based on some set of credentials. Authorization, the process of deciding whether to allow
an entity access to, or to perform operations upon, other entities is outside the scope of
Zend_Auth
. For more information about authorization and access
control with Zend Framework, please see Zend_Acl
.
Nota
The Zend_Auth
class implements the Singleton pattern - only one
instance of the class is available - through its static
getInstance()
method. This means that using the
new operator and the clone keyword will not
work with the Zend_Auth
class; use
Zend_Auth::getInstance()
instead.
A Zend_Auth
adapter is used to authenticate against a particular
type of authentication service, such as LDAP,
RDBMS, or file-based storage. Different adapters are likely to have
vastly different options and behaviors, but some basic things are common among
authentication adapters. For example, accepting authentication credentials (including a
purported identity), performing queries against the authentication service, and
returning results are common to Zend_Auth
adapters.
Each Zend_Auth
adapter class implements
Zend_Auth_Adapter_Interface
. This interface defines one method,
authenticate()
, that an adapter class must implement for
performing an authentication query. Each adapter class must be prepared prior to
calling authenticate()
. Such adapter preparation includes
setting up credentials (e.g., username and password) and defining values for
adapter-specific configuration options, such as database connection settings for a
database table adapter.
The following is an example authentication adapter that requires a username and password to be set for authentication. Other details, such as how the authentication service is queried, have been omitted for brevity:
class MyAuthAdapter implements Zend_Auth_Adapter_Interface { /** * Sets username and password for authentication * * @return void */ public function __construct($username, $password) { // ... } /** * Performs an authentication attempt * * @throws Zend_Auth_Adapter_Exception If authentication cannot * be performed * @return Zend_Auth_Result */ public function authenticate() { // ... } }
As indicated in its docblock, authenticate()
must return an
instance of Zend_Auth_Result
(or of a class derived from
Zend_Auth_Result
). If for some reason performing an
authentication query is impossible, authenticate()
should
throw an exception that derives from
Zend_Auth_Adapter_Exception
.
Zend_Auth
adapters return an instance of
Zend_Auth_Result
with authenticate()
in
order to represent the results of an authentication attempt. Adapters populate the
Zend_Auth_Result
object upon construction, so that the following
four methods provide a basic set of user-facing operations that are common to the
results of Zend_Auth
adapters:
-
isValid()
- returnsTRUE
if and only if the result represents a successful authentication attempt -
getCode()
- returns aZend_Auth_Result
constant identifier for determining the type of authentication failure or whether success has occurred. This may be used in situations where the developer wishes to distinguish among several authentication result types. This allows developers to maintain detailed authentication result statistics, for example. Another use of this feature is to provide specific, customized messages to users for usability reasons, though developers are encouraged to consider the risks of providing such detailed reasons to users, instead of a general authentication failure message. For more information, see the notes below. -
getIdentity()
- returns the identity of the authentication attempt -
getMessages()
- returns an array of messages regarding a failed authentication attempt
A developer may wish to branch based on the type of authentication result in order to perform more specific operations. Some operations developers might find useful are locking accounts after too many unsuccessful password attempts, flagging an IP address after too many nonexistent identities are attempted, and providing specific, customized authentication result messages to the user. The following result codes are available:
Zend_Auth_Result::SUCCESS Zend_Auth_Result::FAILURE Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID Zend_Auth_Result::FAILURE_UNCATEGORIZED
The following example illustrates how a developer may branch on the result code:
// inside of AuthController / loginAction $result = $this->_auth->authenticate($adapter); switch ($result->getCode()) { case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND: /** do stuff for nonexistent identity **/ break; case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID: /** do stuff for invalid credential **/ break; case Zend_Auth_Result::SUCCESS: /** do stuff for successful authentication **/ break; default: /** do stuff for other failure **/ break; }
Authenticating a request that includes authentication credentials is useful per se, but it is also important to support maintaining the authenticated identity without having to present the authentication credentials with each request.
HTTP is a stateless protocol, however, and techniques such as cookies and sessions have been developed in order to facilitate maintaining state across multiple requests in server-side web applications.
By default, Zend_Auth
provides persistent storage of the
identity from a successful authentication attempt using the PHP
session. Upon a successful authentication attempt,
Zend_Auth::authenticate()
stores the identity from the
authentication result into persistent storage. Unless configured otherwise,
Zend_Auth
uses a storage class named
Zend_Auth_Storage_Session
, which, in turn, uses
Zend_Session
. A custom
class may instead be used by providing an object that implements
Zend_Auth_Storage_Interface
to
Zend_Auth::setStorage()
.
Nota
If automatic persistent storage of the identity is not appropriate for a
particular use case, then developers may forgot using the
Zend_Auth
class altogether, instead using an adapter
class directly.
Exemplo 56. Modifying the Session Namespace
Zend_Auth_Storage_Session
uses a session namespace of
'Zend_Auth
'. This namespace may be overridden by passing
a different value to the constructor of
Zend_Auth_Storage_Session
, and this value is internally
passed along to the constructor of
Zend_Session_Namespace
. This should occur before
authentication is attempted, since
Zend_Auth::authenticate()
performs the automatic
storage of the identity.
// Save a reference to the Singleton instance of Zend_Auth $auth = Zend_Auth::getInstance(); // Use 'someNamespace' instead of 'Zend_Auth' $auth->setStorage(new Zend_Auth_Storage_Session('someNamespace')); /** * @todo Set up the auth adapter, $authAdapter */ // Authenticate, saving the result, and persisting the identity on // success $result = $auth->authenticate($authAdapter);
Sometimes developers may need to use a different identity storage mechanism than
that provided by Zend_Auth_Storage_Session
. For such cases
developers may simply implement Zend_Auth_Storage_Interface
and supply an instance of the class to
Zend_Auth::setStorage()
.
Exemplo 57. Using a Custom Storage Class
In order to use an identity persistence storage class other than
Zend_Auth_Storage_Session
, a developer implements
Zend_Auth_Storage_Interface
:
class MyStorage implements Zend_Auth_Storage_Interface { /** * Returns true if and only if storage is empty * * @throws Zend_Auth_Storage_Exception If it is impossible to * determine whether storage * is empty * @return boolean */ public function isEmpty() { /** * @todo implementation */ } /** * Returns the contents of storage * * Behavior is undefined when storage is empty. * * @throws Zend_Auth_Storage_Exception If reading contents from * storage is impossible * @return mixed */ public function read() { /** * @todo implementation */ } /** * Writes $contents to storage * * @param mixed $contents * @throws Zend_Auth_Storage_Exception If writing $contents to * storage is impossible * @return void */ public function write($contents) { /** * @todo implementation */ } /** * Clears contents from storage * * @throws Zend_Auth_Storage_Exception If clearing contents from * storage is impossible * @return void */ public function clear() { /** * @todo implementation */ } }
In order to use this custom storage class,
Zend_Auth::setStorage()
is invoked before an
authentication query is attempted:
// Instruct Zend_Auth to use the custom storage class Zend_Auth::getInstance()->setStorage(new MyStorage()); /** * @todo Set up the auth adapter, $authAdapter */ // Authenticate, saving the result, and persisting the identity on // success $result = Zend_Auth::getInstance()->authenticate($authAdapter);
There are two provided ways to use Zend_Auth
adapters:
-
indirectly, through
Zend_Auth::authenticate()
-
directly, through the adapter's
authenticate()
method
The following example illustrates how to use a Zend_Auth
adapter
indirectly, through the use of the Zend_Auth
class:
// Get a reference to the singleton instance of Zend_Auth $auth = Zend_Auth::getInstance(); // Set up the authentication adapter $authAdapter = new MyAuthAdapter($username, $password); // Attempt authentication, saving the result $result = $auth->authenticate($authAdapter); if (!$result->isValid()) { // Authentication failed; print the reasons why foreach ($result->getMessages() as $message) { echo "$message\n"; } } else { // Authentication succeeded; the identity ($username) is stored // in the session // $result->getIdentity() === $auth->getIdentity() // $result->getIdentity() === $username }
Once authentication has been attempted in a request, as in the above example, it is a simple matter to check whether a successfully authenticated identity exists:
$auth = Zend_Auth::getInstance(); if ($auth->hasIdentity()) { // Identity exists; get it $identity = $auth->getIdentity(); }
To remove an identity from persistent storage, simply use the
clearIdentity()
method. This typically would be used for
implementing an application "logout" operation:
Zend_Auth::getInstance()->clearIdentity();
When the automatic use of persistent storage is inappropriate for a particular use
case, a developer may simply bypass the use of the Zend_Auth
class, using an adapter class directly. Direct use of an adapter class involves
configuring and preparing an adapter object and then calling its
authenticate()
method. Adapter-specific details are discussed
in the documentation for each adapter. The following example directly utilizes
MyAuthAdapter
:
// Set up the authentication adapter $authAdapter = new MyAuthAdapter($username, $password); // Attempt authentication, saving the result $result = $authAdapter->authenticate(); if (!$result->isValid()) { // Authentication failed; print the reasons why foreach ($result->getMessages() as $message) { echo "$message\n"; } } else { // Authentication succeeded // $result->getIdentity() === $username }