Zend_Authの概要

この記事では、 Zend_Authコンポーネントの機能の概要を説明し、Zend Frameworkに基づくアプリケーションでのユーザー認証の実装の一般的な考え方を示します。 与えられた例の基礎として、記事「Introduction to Zend Framework」の資料が使用されました 。 サンプルはZend Frameworkバージョン0.9、0.9.1、0.9.2でテストされており、新しいバージョンでは動作する可能性が高いですが、以前のバージョンでは動作しません。

投稿者:ロブアレン、 http://akrabat.com
オリジナル: http : //akrabat.com/zend-auth-tutorial
翻訳: Alexander Musaev、 http //paradigm.ru

印刷用のPDFバージョン: http : //archive.paradigm.ru/zend_auth.pdf

始める前に

この例で使用するユーザー認証メカニズムの実装は、PHPセッションに基づいています。 php.ini session.save_pathパラメーターが、Webサーバーが書き込み可能なディレクトリに設定されていることを確認してください。

認証

認証または認証は、サブジェクトと、一意の情報を使用して偽装しようとしているサブジェクトの適合性を検証するための手順です。 この手順は、識別(情報のやり取りの対象の認識)および承認(システムリソースへのアクセス権の検証)とは区別する必要があります。

Webアプリケーションのコンテキストでは、認証は通常、ユーザーがWebサーバー上の自分のアカウントと名前(「ログイン」)およびパスワードを照合するかどうかをチェックすることを意味します。 Zend Frameworkに基づいたこのようなメカニズムの実装の例として、CDデータベースにこのチェックを追加します(記事「Introduction to Zend Framework」で実装されたWebアプリケーション)。

これには次のものが必要です。
  1. ユーザー用のデータベースにテーブルを作成します(そして、新しいアカウントを追加します)。
  2. ログインフォームを作成します。
  3. 出入りするアクションを含むコントローラーを実装します。
  4. ページテンプレートの一般的なフラグメントにログアウトする機能を追加します。
  5. ユーザーが何らかのアクションを実行できるようにする前に、ユーザーがログインしていることの確認を追加します。

ユーザー表

最初に必要なのは、ユーザーアカウントを保存するためのデータベース内のテーブルです。 彼女のスキームは次のようになります。

フィールド種類ヌル?フィールドオプション
id整数いや主キー、自動インクリメント
ユーザー名バルチャー(50)いや一意のキー
パスワードバルチャー(50)いや-
実名バルチャー(100)いや-


MySQLを使用する場合、このようなテーブルは次のクエリで作成できます。
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)
)

テストユーザーアカウントを追加する必要があります。
INSERT INTO users (id, username, password, real_name)
VALUES (1, 'rob', 'rob', 'Rob Allen');

MySQLクライアントプログラムを使用してこれらのSQLクエリを実行します。 ユーザー名とパスワードは、必要に応じて他の値に変更できます。

ブートファイル

システムへのユーザーの登録(エントリと終了)を追跡できるようにするには、PHPセッションのメカニズムを使用する必要があります。 Zend Frameworkは、便利な作業のために、特別なクラスZend_Session_Namespace提供していZend_Session_Namespace

ブートストラップファイルに次の変更を加える必要があります。

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();
...

ここで必要なことは、 Zend_AuthクラスZend_Auth接続され、 Zend_AuthデータベースdbAdapter登録されていることを確認することだけです。 このアダプターは、後で許可コントローラーからアクセスする必要があるため、レジストリーに保管されます。

承認コントローラー

入力アクションと出力アクションをグループ化するには、特別なコントローラーが必要です。 AuthControllerという名前を付けることは論理的AuthController 。 コンストラクターで実装を開始し、デフォルトのアクション( indexAction() )を定義しましょう。

zf-tutorial/application/controllers/AuthController.php:
<?php
class AuthController extends Zend_Controller_Action
{
function init()
{
$this->initView();
$this->view->baseUrl = $this->_request->getBaseUrl();
}
function indexAction()
{
$this->_redirect('/');
}
}

コントローラークラスのコンストラクターで、ビューが初期化baseUrlbaseUrl変数の値がbaseUrlます。 コンストラクターに加えて、 indexAction()アクションがクラスで定義されZend_Controller_Action 。これは、 Zend_Controller_Actionすべての子孫にとって必須の要件です。 loginAction()およびlogoutAction()のみを使用することを考慮すると、デフォルトのアクションは必要ないため、対応するURLからサイトのメインページにユーザーをリダイレクトします。

ログイン

システムに入るには、特別なフォームが必要です。 AuthController login AuthControllerは、 IndexControllerアクションがフォームでIndexControllerするのと同じ方法でそれと対話します。 フォームテンプレートは、ファイルviews/scripts/auth/login.phtmlにあり、そこからのデータはAuthController::loginAction()メソッドによって処理されます。

ログインフォームは非常にシンプルで、ユーザー名とパスワード用の2つのフィールドのみが含まれています。

zf-tutorial/application/views/scripts/auth/login.phtml:
<?php echo $this->render('header.phtml'); ?>
<h1><?php echo $this->escape($this->title); ?></h1>
<?php if(!empty($this->message)) :?>
<div id="message">
<?php echo $this->escape($this->message);?>
</div>
<?php endif; ?>
<form action="<?php echo $this->baseUrl ?>/auth/login" method="post">
<div>
<label for="username">Username</label>
<input type="text" name="username" value=""/>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" value=""/>
</div>
<div id="formbutton">
<input type="submit" name="login" value="Login" />
</div>
</form>
<?php echo $this->render('footer.phtml'); ?>

テンプレートには、ページの最初と最後にそれぞれheader.phtmlfooter.phtml表示されます。 変数$this→messageメッセージからの$this→messageは、その値が空でない場合にのみ表示されることに注意してください。 この変数は、ログイン中にエラーが発生し、ユーザーがそれを報告する必要がある場合に使用されます。 テンプレートの残りの部分は、ログインフォーム自体です。

フォームの準備ができたので、それを操作するコントローラーの作成に進みます。

zf-tutorial/application/controllers/AuthController.php:
class AuthController extends Zend_Controller_Action
{
...
function loginAction()
{
$this->view->message = '';
$this->view->title = "Log in";
$this->render();
}
}

フォームを表示するには、タイトルとメッセージ本文を設定する必要があります。その後、URLをクリックしてフォームを表示できます http://zf-tutorial/auth/login http://zf-tutorial/auth/login 。 この場合、送信されたデータをどのように処理するのでしょうか? これを行うには、 IndexControllerレコードフォームを編集および追加する場合に使用したのと同じメソッドを使用します。 つまり、サーバーへのアクセス方法がPOSTの場合にのみ、データ処理が実行されます。 それ以外の場合、 loginアクションは単にフォームを返しloginloginAction()必要な変更を以下に示します。

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();
}
}

上記のコードをステップごとに検討してください。
// 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 {
...

ここでは、いつものように、POST配列からユーザー名とパスワードを抽出し、HTMLフィルターでそれらの値を処理します。 この場合に使用されるgetPost()関数は、パラメーターで指定された変数の存在を自動的にチェックし、POSTで変数が見つからない場合は空の値を返します。

認証プロセスは、ユーザー名が指定されている場合にのみ続行されます。 空の場合、 Zend_Auth認証しようとすると例外がスローされます。
// 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');

Zend_Authは、アダプターサブシステムを使用して認証データを操作します。 このようなアダプターは、リレーショナルデータベース、LDAP、シンプルファイルなどの異種データストアへの統合されたインターフェイスを提供します。 この例では、データベースがこの目的に使用されるため、 Zend_Auth_Adapter_DbTableアダプターがZend_Auth_Adapter_DbTableます。 初期化するには、データベースパラメータ(ユーザーテーブルの名前とそのフィールドの名前)を設定する必要があります。
// 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);

認証手順自体を実行するために、 Zend_Authクラスのauthenticate()メソッドの呼び出しがZend_Authます。 この場合、認証結果はセッションに自動的に保存されます。
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('/');

認証が成功した場合、データベースのユーザーアカウントはZend_Authシングルトン内に完全に保存されます(もちろん、パスワードは除きます)。
} else {
// failure: clear database row from session
$this->view->message = 'Login failed.';
}
}

ユーザー名とパスワードの検証に合格しなかった場合は、変数messageを通じてユーザーに通知しmessage 。 これで、ログインの認証プロセスが完了しました。

出口

ログアウトはログインよりもはるかに簡単です。 必要なのは、 Zend_Authシングルトン内のデータをクリアすることだけです。 これは、 logoutAction()コントローラーのlogoutAction()アクションで実装されます。 したがって、終了するには、URLに移動するだけです。 http://zftutorial/auth/logout http://zftutorial/auth/logout

zf-tutorial/application/controllers/AuthController.php:
class AuthController extends Zend_Controller_Action
{
...
function logoutAction()
{
Zend_Auth::getInstance()->clearIdentity();
$this->_redirect('/');
}
}

logoutAction()関数は非常に単純なので、コメントするものはまったくありません。

ユーザーがクリックしてWebアプリケーションを終了できる特別なリンクをユーザーに提供する必要があります。 最も簡単な方法は、 footerテンプレート内です。 さらに、承認が成功したことを確認するために、ユーザーに名前を通知します。 ユーザー名は、対応するデータベーステーブルのreal_nameフィールドに保存され、 Zend_Authからアクセスできます。 最初に行う必要があるのは、この値をビューに渡すことです。これは、 IndexController()コントローラーのinit()関数内で行いinit()

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();
}
...
}

Zend_Authがシングルトンであると非常に便利です。 それ以外の場合、この場合、その内容をレジストリに保存する必要があります。

次に、 footer.phtmlファイルに変更を加える必要があります。

zf-tutorial/application/views/footer.phtml:
<?php if($this->user) : ?>
<p id="logged-in">Logged in as <?php
echo $this->escape($this->user->real_name);?>.
<a href="<?php echo $this->baseUrl ?>/auth/logout">Logout</a></p>
<?php endif; ?>
</div>
</body>
</html>

上記のコードには、根本的に新しいものは含まれていません。 escape()を使用して、ブラウザにユーザー名が正しく表示されることを確認します。 baseUrl変数の値は、リンクを正しく形成するために使用されます。

ログアウト機能の準備ができました。

アクション保護

私たちがやるべきことは、ユーザーがログインする前にアクションが利用できないことを確認することだけです。

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');
}
}
...
}

標準名がpreDispatch()関数は、コントローラーアクションの前に自動的に呼び出されます。 hasIdentity()オブジェクトのhasIdentity()メソッドを使用して、ログインが完了したかどうかを確認します。 そして、そうでない場合は、ユーザーをauth/loginリダイレクトしauth/login

これで承認作業が完了しました。

おわりに

Zend Frameworkに基づくユーザー認証関数の実装の上記の例は非常に単純ですが、 Zend_Authはいくつかのコントローラーでより複雑なアプリケーションを保護するために使用できる多くの便利な機能がまだあることを理解する必要があります。 Zend_Aclコンポーネントに実装されている承認システムも影響を受けませんでした。 後者はZend_Authと組み合わせて使用​​し、ユーザーアクセスレベルをアクションまたはデータに区別するように設計されていますが、これは別の議論のトピックです。

元の記事に関するすべてのコメントは、rob @ akrabat.comの著者に送信できます。 ロシア語の翻訳に関するコメントは、musayev @ yandex.ruに送信してください。

更新:記事のプログラムの例を含むアーカイブは、著者のウェブサイトzend_auth-tutorial_104.zipにあります。

Source: https://habr.com/ru/post/J31178/


All Articles