| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- Reviewed: no -->
- <sect1 id="zend.auth.introduction">
- <title>Introduction</title>
- <para>
- <classname>Zend_Auth</classname> provides an <acronym>API</acronym> for authentication and
- includes concrete authentication adapters for common use case scenarios.
- </para>
- <para>
- <classname>Zend_Auth</classname> is concerned only with <emphasis>authentication</emphasis>
- and not with <emphasis>authorization</emphasis>. 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
- <classname>Zend_Auth</classname>. For more information about authorization and access
- control with Zend Framework, please see <link
- linkend="zend.acl"><classname>Zend_Acl</classname></link>.
- </para>
- <note>
- <para>
- The <classname>Zend_Auth</classname> class implements the Singleton pattern - only one
- instance of the class is available - through its static
- <methodname>getInstance()</methodname> method. This means that using the
- <emphasis>new</emphasis> operator and the <emphasis>clone</emphasis> keyword will not
- work with the <classname>Zend_Auth</classname> class; use
- <methodname>Zend_Auth::getInstance()</methodname> instead.
- </para>
- </note>
- <sect2 id="zend.auth.introduction.adapters">
- <title>Adapters</title>
- <para>
- A <classname>Zend_Auth</classname> adapter is used to authenticate against a particular
- type of authentication service, such as <acronym>LDAP</acronym>,
- <acronym>RDBMS</acronym>, 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 <classname>Zend_Auth</classname> adapters.
- </para>
- <para>
- Each <classname>Zend_Auth</classname> adapter class implements
- <classname>Zend_Auth_Adapter_Interface</classname>. This interface defines one method,
- <methodname>authenticate()</methodname>, that an adapter class must implement for
- performing an authentication query. Each adapter class must be prepared prior to
- calling <methodname>authenticate()</methodname>. 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.
- </para>
- <para>
- 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:
- </para>
- <programlisting language="php"><![CDATA[
- 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()
- {
- // ...
- }
- }
- ]]></programlisting>
- <para>
- As indicated in its docblock, <methodname>authenticate()</methodname> must return an
- instance of <classname>Zend_Auth_Result</classname> (or of a class derived from
- <classname>Zend_Auth_Result</classname>). If for some reason performing an
- authentication query is impossible, <methodname>authenticate()</methodname> should
- throw an exception that derives from
- <classname>Zend_Auth_Adapter_Exception</classname>.
- </para>
- </sect2>
- <sect2 id="zend.auth.introduction.results">
- <title>Results</title>
- <para>
- <classname>Zend_Auth</classname> adapters return an instance of
- <classname>Zend_Auth_Result</classname> with <methodname>authenticate()</methodname> in
- order to represent the results of an authentication attempt. Adapters populate the
- <classname>Zend_Auth_Result</classname> object upon construction, so that the following
- four methods provide a basic set of user-facing operations that are common to the
- results of <classname>Zend_Auth</classname> adapters:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>isValid()</methodname> - returns <constant>TRUE</constant> if and
- only if the result represents a successful authentication attempt
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getCode()</methodname> - returns a
- <classname>Zend_Auth_Result</classname> 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.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getIdentity()</methodname> - returns the identity of the
- authentication attempt
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getMessages()</methodname> - returns an array of messages
- regarding a failed authentication attempt
- </para>
- </listitem>
- </itemizedlist>
- <para>
- 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:
- </para>
- <programlisting language="php"><![CDATA[
- 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
- ]]></programlisting>
- <para>
- The following example illustrates how a developer may branch on the result code:
- </para>
- <programlisting language="php"><![CDATA[
- // 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;
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.auth.introduction.persistence">
- <title>Identity Persistence</title>
- <para>
- 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.
- </para>
- <para>
- <acronym>HTTP</acronym> 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.
- </para>
- <sect3 id="zend.auth.introduction.persistence.default">
- <title>Default Persistence in the PHP Session</title>
- <para>
- By default, <classname>Zend_Auth</classname> provides persistent storage of the
- identity from a successful authentication attempt using the <acronym>PHP</acronym>
- session. Upon a successful authentication attempt,
- <methodname>Zend_Auth::authenticate()</methodname> stores the identity from the
- authentication result into persistent storage. Unless configured otherwise,
- <classname>Zend_Auth</classname> uses a storage class named
- <classname>Zend_Auth_Storage_Session</classname>, which, in turn, uses
- <link linkend="zend.session"><classname>Zend_Session</classname></link>. A custom
- class may instead be used by providing an object that implements
- <classname>Zend_Auth_Storage_Interface</classname> to
- <methodname>Zend_Auth::setStorage()</methodname>.
- </para>
- <note>
- <para>
- If automatic persistent storage of the identity is not appropriate for a
- particular use case, then developers may forgot using the
- <classname>Zend_Auth</classname> class altogether, instead using an adapter
- class directly.
- </para>
- </note>
- <example id="zend.auth.introduction.persistence.default.example">
- <title>Modifying the Session Namespace</title>
- <para>
- <classname>Zend_Auth_Storage_Session</classname> uses a session namespace of
- '<classname>Zend_Auth</classname>'. This namespace may be overridden by passing
- a different value to the constructor of
- <classname>Zend_Auth_Storage_Session</classname>, and this value is internally
- passed along to the constructor of
- <classname>Zend_Session_Namespace</classname>. This should occur before
- authentication is attempted, since
- <methodname>Zend_Auth::authenticate()</methodname> performs the automatic
- storage of the identity.
- </para>
- <programlisting language="php"><![CDATA[
- // 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);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.auth.introduction.persistence.custom">
- <title>Implementing Customized Storage</title>
- <para>
- Sometimes developers may need to use a different identity storage mechanism than
- that provided by <classname>Zend_Auth_Storage_Session</classname>. For such cases
- developers may simply implement <classname>Zend_Auth_Storage_Interface</classname>
- and supply an instance of the class to
- <methodname>Zend_Auth::setStorage()</methodname>.
- </para>
- <example id="zend.auth.introduction.persistence.custom.example">
- <title>Using a Custom Storage Class</title>
- <para>
- In order to use an identity persistence storage class other than
- <classname>Zend_Auth_Storage_Session</classname>, a developer implements
- <classname>Zend_Auth_Storage_Interface</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- 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
- */
- }
- }
- ]]></programlisting>
- <para>
- In order to use this custom storage class,
- <methodname>Zend_Auth::setStorage()</methodname> is invoked before an
- authentication query is attempted:
- </para>
- <programlisting language="php"><![CDATA[
- // 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);
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.auth.introduction.using">
- <title>Usage</title>
- <para>
- There are two provided ways to use <classname>Zend_Auth</classname> adapters:
- </para>
- <orderedlist>
- <listitem>
- <para>
- indirectly, through <methodname>Zend_Auth::authenticate()</methodname>
- </para>
- </listitem>
- <listitem>
- <para>
- directly, through the adapter's <methodname>authenticate()</methodname> method
- </para>
- </listitem>
- </orderedlist>
- <para>
- The following example illustrates how to use a <classname>Zend_Auth</classname> adapter
- indirectly, through the use of the <classname>Zend_Auth</classname> class:
- </para>
- <programlisting language="php"><![CDATA[
- // 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
- }
- ]]></programlisting>
- <para>
- 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:
- </para>
- <programlisting language="php"><![CDATA[
- $auth = Zend_Auth::getInstance();
- if ($auth->hasIdentity()) {
- // Identity exists; get it
- $identity = $auth->getIdentity();
- }
- ]]></programlisting>
- <para>
- To remove an identity from persistent storage, simply use the
- <methodname>clearIdentity()</methodname> method. This typically would be used for
- implementing an application "logout" operation:
- </para>
- <programlisting language="php"><![CDATA[
- Zend_Auth::getInstance()->clearIdentity();
- ]]></programlisting>
- <para>
- When the automatic use of persistent storage is inappropriate for a particular use
- case, a developer may simply bypass the use of the <classname>Zend_Auth</classname>
- class, using an adapter class directly. Direct use of an adapter class involves
- configuring and preparing an adapter object and then calling its
- <methodname>authenticate()</methodname> method. Adapter-specific details are discussed
- in the documentation for each adapter. The following example directly utilizes
- <classname>MyAuthAdapter</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- // 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
- }
- ]]></programlisting>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|