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アプリケーション)。
これには次のものが必要です。
- ユーザー用のデータベースにテーブルを作成します(そして、新しいアカウントを追加します)。
- ログインフォームを作成します。
- 出入りするアクションを含むコントローラーを実装します。
- ページテンプレートの一般的なフラグメントにログアウトする機能を追加します。
- ユーザーが何らかのアクションを実行できるようにする前に、ユーザーがログインしていることの確認を追加します。
ユーザー表
最初に必要なのは、ユーザーアカウントを保存するためのデータベース内のテーブルです。 彼女のスキームは次のようになります。フィールド | 種類 | ヌル? | フィールドオプション |
---|---|---|---|
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('/');
}
}
コントローラークラスのコンストラクターで、ビューが初期化
baseUrl
、
baseUrl
変数の値が
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.phtml
と
footer.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
アクションは単にフォームを返し
login
。
loginAction()
必要な変更を以下に示します。
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にあります。