| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.auth.introduction">
- <title>Введение</title>
- <para>
- <classname>Zend_Auth</classname> предоставляет <acronym>API</acronym> для аутентификации и
- включает в себя конкретные адаптеры для общих случаев применения.
- </para>
- <para>
- Задачей <classname>Zend_Auth</classname> является <emphasis>аутентификация</emphasis>,
- но не <emphasis>авторизация</emphasis>. Аутентификацию в общих чертах можно характеризовать
- как процесс определения, действительно ли сущность является тем, чем она претендует быть
- (то есть идентификация), на основании некоторого набора учетных данных. Авторизация же -
- процесс определения того, можно ли предоставить сущности доступ или разрешить выполнить
- действие, и это полностью вне сферы компетенции <classname>Zend_Auth</classname>.
- Дополнительную информацию об авторизации и контроле доступа в Zend Framework смотрите в
- <link linkend="zend.acl"><classname>Zend_Acl</classname></link>.
- </para>
- <note>
- <para>
- Класс <classname>Zend_Auth</classname> реализует паттерн Синглтон - только один экзмепляр
- класса доступен – через статический метод <methodname>getInstance()</methodname>. Это
- означает, что ключевые слова <emphasis>new</emphasis> или <emphasis>clone</emphasis> не
- будут работать с классом <classname>Zend_Auth</classname>. Вместо них используйте
- <methodname>Zend_Auth::getInstance()</methodname>.
- </para>
- </note>
- <sect2 id="zend.auth.introduction.adapters">
- <title>Адаптеры</title>
- <para>
- Адаптер <classname>Zend_Auth</classname> используется дла аутентификации посредством
- определенного сервиса, такого как <acronym>LDAP</acronym>, <acronym>СУРБД</acronym> или
- файлового хранилища. Адаптеры могут значительно различаться, но некоторые основные черты
- характерны для всех. Например, все адаптеры <classname>Zend_Auth</classname> принимают
- учетные данные, выполненяют запрос к аутентификационному сервису и возвращают результат.
-
- </para>
- <para>
- Каждый адаптер <classname>Zend_Auth</classname> реализует
- <classname>Zend_Auth_Adapter_Interface</classname>. Этот интерфейс определяет лишь один
- метод: <methodname>authenticate()</methodname>, который должен быть реализовать для
- выполнения аутентификационного запроса. Адаптер должен быть настроен до вызова
- <methodname>authenticate()</methodname>, настройка включает в себя установку учетных
- данных(например, логин и пароль) и определение специфичных значений, таких как настройки
- подключения к базе данных для адаптера таблиц БД.
- </para>
- <para>
- Это пример адаптера, требующего установки логина и пароля для аутентификации. Прочие
- детали, например каким образом аутентификационный сервис запрашивается, были опущены для
- кратости:
- </para>
- <programlisting language="php"><![CDATA[
- class MyAuthAdapter implements Zend_Auth_Adapter_Interface
- {
- /**
- * Устанавливает логин и пароль для аутентификации
- *
- * @return void
- */
- public function __construct($username, $password)
- {
- // ...
- }
- /**
- * Выполняет попытку аутентификации
- *
- * @throws Zend_Auth_Adapter_Exception Если аутентификация не может быть выполнена
- * @return Zend_Auth_Result
- */
- public function authenticate()
- {
- // ...
- }
- }
- ]]></programlisting>
- <para>
- Как указано в докблоке, <methodname>authenticate()</methodname> должен вернуть экземпляр
- <classname>Zend_Auth_Result</classname> (или унаследованный от него). Если по какой либо
- причине выполнение аутентификации невозможно, <methodname>authenticate()</methodname>
- должен бросить исключение, происходящее от
- <classname>Zend_Auth_Adapter_Exception</classname>.
- </para>
- </sect2>
- <sect2 id="zend.auth.introduction.results">
- <title>Результат аутентификации</title>
- <para>
- Метод <methodname>authenticate()</methodname> адаптера <classname>Zend_Auth</classname>
- возвращает экзмепляр <classname>Zend_Auth_Result</classname> для представления
- результата попытки аутентификации. Объект <classname>Zend_Auth_Result</classname>
- заполняется адаптером при создании, и следующие четыре метода представляют его базовый
- набор операций:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <methodname>isValid()</methodname> - возвращает <constant>TRUE</constant> только
- в случае успешной попытки аутентификации.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getCode()</methodname> - возвращает значение одной из констант
- <classname>Zend_Auth_Result</classname> для обозначения успешности попытки или
- типа возникшей ошибки. Это может быть использовано в ситуации, когда разработчик
- хочет различать результаты попыток аутентификации. К примеру, он может вести
- детальную статистку всех попыток, либо выводить нестандартные сообщения для
- удобства пользователей. Но при этом стоит учитывать риски предоставления
- пользователям подробных сведений вместо стандартных сообщений о неудаче.
- Подробнее о возвращаемых значениях смотрите ниже.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getIdentity()</methodname> - возвращает идентификатор, полученный в
- результе аутентификации.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>getMessages()</methodname> - возвращает массив сообщений о ошибках,
- возникших в процессе попытки аутентификации.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Разработчик может пожелать выполнять различные действия на основании результата
- аутентификации. Например, он может найти полезным блокировку аккаунтов после нескольких
- вводов неправильного пароля, пометку IP после слишком многих попыток аутентификации
- с несуществующими данными или вывод настраиваемых сообщений о результате аутентификации.
- Существуют следующие коды результата:
- </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>
- Этот пример показывает, как разработчик может различным образом обработать результат
- аутентификации, используя значение кода:
- </para>
- <programlisting language="php"><![CDATA[
- // в AuthController / loginAction
- $result = $this->_auth->authenticate($adapter);
- switch ($result->getCode()) {
- case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
- /** Выполнить действия при несуществующем идентификаторе **/
- break;
- case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
- /** Выполнить действия при некорректных учетных данных **/
- break;
- case Zend_Auth_Result::SUCCESS:
- /** Выполнить действия при успешной аутентификации **/
- break;
- default:
- /** Выполнить действия для остальных ошибок **/
- break;
- }
- ]]></programlisting>
- </sect2>
- <sect2 id="zend.auth.introduction.persistence">
- <title>Постоянное хранение идентификатора пользователя</title>
- <para>
- Аутентификация запроса, содержащего учетные данные, важна сама по себе, но также важно
- поддерживать сохранение идентификатора без необходимости передачи учетных данных с
- каждым запросом.
- </para>
- <para>
- Протокол <acronym>HTTP</acronym> не имеет состояний, однако были разработаны такие
- технологии как куки(cookies) и сессии для поддержки состояния на стороне сервера между
- несколькими запросами к веб приложению.
- </para>
- <sect3 id="zend.auth.introduction.persistence.default">
- <title>Сохранение идентификатора в сессии PHP, по умолчанию</title>
- <para>
- По умолчанию, <classname>Zend_Auth</classname> обеспечивает постоянное хранение
- идентификатора полученного в результате успешной попытки аутентификации в
- <acronym>PHP</acronym> сессии.
- </para>
- <para>
- При успешной попытке, <methodname>Zend_Auth::authenticate()</methodname> сохраняет
- идентификатор в постоянном хранилище. Если не настроено по другому,
- <classname>Zend_Auth</classname> использует класс хранилища
- <classname>Zend_Auth_Storage_Session</classname>, который в свою очередь использует
- <link linkend="zend.session"><classname>Zend_Session</classname></link>.
- Вместо него может быть использован пользовательский класс, для этого нужно
- передать <methodname>Zend_Auth::setStorage()</methodname> объект, реализующий
- <classname>Zend_Auth_Storage_Interface</classname>.
- </para>
- <note>
- <para>
- Если автоматическое сохранение идентификатора не подходит в каком-либо
- конкретном случае, тогда разработчику следует отказаться от использования класса
- <classname>Zend_Auth</classname> и использовать адаптер напрямую.
- </para>
- </note>
- <example id="zend.auth.introduction.persistence.default.example">
- <title>Изменение пространства имен в сессии</title>
- <para>
- <classname>Zend_Auth_Storage_Session</classname> использует пространство имен
- '<classname>Zend_Auth</classname>'. Оно может быть переопределено передачей
- другого значения конструктору <classname>Zend_Auth_Storage_Session</classname>,
- которое будет дальше передано конструктору
- <classname>Zend_Session_Namespace</classname>. Это нужно сделать до того, как
- будет произведена попытка аутентификации, так как
- <methodname>Zend_Auth::authenticate()</methodname> выполняет автоматическое
- сохранение идентификатора.
- </para>
- <programlisting language="php"><![CDATA[
- // Получение синглтон экземпляра Zend_Auth
- $auth = Zend_Auth::getInstance();
- // Установка 'someNamespace' вместо 'Zend_Auth'
- $auth->setStorage(new Zend_Auth_Storage_Session('someNamespace'));
- /**
- * @todo подготовка адаптера, $authAdapter
- */
- // Аутентификация, сохранение результата, и хранение идентификатора
- // при успехе.
- $result = $auth->authenticate($authAdapter);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.auth.introduction.persistence.custom">
- <title>Реализация пользовательского хранилища</title>
- <para>
- Иногда разработчику может понадобиться использовать иной механизм хранения
- идентификаторов, нежели предоставляется в
- <classname>Zend_Auth_Storage_Session</classname>. В том случае он может реализовать
- <classname>Zend_Auth_Storage_Interface</classname> и передать экземпляр
- методу <methodname>Zend_Auth::setStorage()</methodname>.
- </para>
- <example id="zend.auth.introduction.persistence.custom.example">
- <title>Использование пользовательского хранилища</title>
- <para>
- Для того, чтобы использовать иной класс хранилища пользовательских
- идентификаторов, нежели <classname>Zend_Auth_Storage_Session</classname>,
- разработчик реализует <classname>Zend_Auth_Storage_Interface</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- class MyStorage implements Zend_Auth_Storage_Interface
- {
- /**
- * Возвращает true, если хранилище пусто
- *
- * @throws Zend_Auth_Storage_Exception В случае если невозможно
- * определить, пусто ли
- * хранилище
- * @return boolean
- */
- public function isEmpty()
- {
- /**
- * @todo реализация
- */
- }
- /**
- * Возвращает содержимое хранилища
- *
- * Поведение неопределено, когда хранилище пусто.
- *
- * @throws Zend_Auth_Storage_Exception Если получение содержимого
- * хранилища невозможно
- * @return mixed
- */
- public function read()
- {
- /**
- * @todo реализация
- */
- }
- /**
- * Записывает $contents в хранилище
- *
- * @param mixed $contents
- * @throws Zend_Auth_Storage_Exception Если запись содержимого в
- * хранилище невозможна
- * @return void
- */
- public function write($contents)
- {
- /**
- * @todo реализация
- */
- }
- /**
- * Очищает содержмое хранилища
- *
- * @throws Zend_Auth_Storage_Exception Если очищение хранилища
- * невозможно
- * @return void
- */
- public function clear()
- {
- /**
- * @todo реализация
- */
- }
- }
- ]]></programlisting>
- <para>
- Для использования этого класса, <methodname>Zend_Auth::setStorage()</methodname>
- вызывается до выполнения попытки авторизации:
- </para>
- <programlisting language="php"><![CDATA[
- // Сказать Zend_Auth использовать пользовательский класс хранилища
- Zend_Auth::getInstance()->setStorage(new MyStorage());
- /**
- * @todo подготовка адаптера, $authAdapter
- */
- // Аутентификация, сохранение результата, и хранение идентификатора
- // при успехе.
- $result = Zend_Auth::getInstance()->authenticate($authAdapter);
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.auth.introduction.using">
- <title>Использование</title>
- <para>
- Существует два пути использования адаптеров <classname>Zend_Auth</classname>:
- </para>
- <orderedlist>
- <listitem>
- <para>
- непрямое, через <methodname>Zend_Auth::authenticate()</methodname>
- </para>
- </listitem>
- <listitem>
- <para>
- прямое, через метод адаптера <methodname>authenticate()</methodname>
- </para>
- </listitem>
- </orderedlist>
- <para>
- Следующий пример показывает, как использовать адаптер <classname>Zend_Auth</classname>
- через класс <classname>Zend_Auth</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- // Получение синглтон экземпляра Zend_Auth
- $auth = Zend_Auth::getInstance();
- // Установка адаптера
- $authAdapter = new MyAuthAdapter($username, $password);
- // Попытка аутентификации, сохранение результата
- $result = $auth->authenticate($authAdapter);
- if (!$result->isValid()) {
- // Попытка неуспешна; вывести сообщения об ошибках
- foreach ($result->getMessages() as $message) {
- echo "$message\n";
- }
- } else {
- // Попытка успешна; идентификатор ($username) сохранен
- // в сессии
- // $result->getIdentity() === $auth->getIdentity()
- // $result->getIdentity() === $username
- }
- ]]></programlisting>
- <para>
- После того как попытка аутентификации была произведена, как показано в примере выше,
- теперь нужно только проверить, существует ли аутентифицированный идентификатор:
- </para>
- <programlisting language="php"><![CDATA[
- $auth = Zend_Auth::getInstance();
- if ($auth->hasIdentity()) {
- // Идентификатор существует; получить его
- $identity = $auth->getIdentity();
- }
- ]]></programlisting>
- <para>
- Для удаления идентификатора из постоянного хранилища, просто используйте метод
- <methodname>clearIdentity()</methodname>. Обычно это используется для реализации
- действия "Выйти":
- </para>
- <programlisting language="php"><![CDATA[
- Zend_Auth::getInstance()->clearIdentity();
- ]]></programlisting>
- <para>
- Когда автоматическое использование постоянного хранилища не подходит, разработчик
- может просто обойти <classname>Zend_Auth</classname> и использовать класс адаптера
- напрямую. Прямое использование адаптера включает в себя настройку, подготовку объекта
- адаптера и последующий вызов его метода, <methodname>authenticate()</methodname>.
- Специфичные для адаптера детали обсуждаются в документации этого адаптера. Следующий
- пример напрямую использует <classname>MyAuthAdapter</classname>:
- </para>
- <programlisting language="php"><![CDATA[
- // Подготовка адаптера
- $authAdapter = new MyAuthAdapter($username, $password);
- // Попытка аутентификации, сохранение результата
- $result = $authAdapter->authenticate();
- if (!$result->isValid()) {
- // Попытка неуспешна; вывести сообщения об ошибках
- foreach ($result->getMessages() as $message) {
- echo "$message\n";
- }
- } else {
- // Попытка успешна;
- // $result->getIdentity() === $username
- }
- ]]></programlisting>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|