Mojavi 初心者講座 セキュリティ
ログイン、セッションを設定する
今回は、ログインの過程を作りながら、MOJAVIのセッションについて学びます。
ディレクトリ構造は以下のようになります。
【modules】 【Security】 【actions】IndexActions.class.php 【views】IndexInputView.class.php 【config】module.ini 【Test】 【template】 【Security】IndexInput.html 【Test】
セキュリティーの設定
MOJAVIは、ユーザーがログインしているかどうかを自動的にチェックする機能を持っています。この機能を有効にするには、以下のような過程で設定を行います。
WEBAPPディレクトリ以下のCONFIGディレクトリを見ます。
【webapp】 【template】 【modules】 【config】←ここを開く
この中に
settings.ini
というファイルがあるので、これを開き、以下の項目を変更します。
LOGIN_MODULE = "Security" LOGIN_ACTION = "Index"
次に
USE_SECURITY = "ON"
USE_SECURITYをONにすることで、ユーザーがログインしているかをアクセスごとにチェックし、ログインしていないユーザーはSecurityモジュールのIndexアクションに飛ばされます。
MOJAVIセキュリティーの仕組み
MOJAVIのセキュリティーは三段階構造になっています。全てはセッション情報を保持するUserオブジェクトに格納されています。
- 一段階目: authenticationオーセンティケーションは、総合的なログインの可否を判断する評価基準で、セッションにTRUE、又はFALSEの形で保存されています。
セッション内でこれがTRUEになっていないユーザーはログイン画面に戻されます。
- 二段階目: credential
クレデンシャルは各アクションへのパスポートで、これが無いと特定のアクションへアクセスできなくなります。
- 三段階目: attribute
Requestオブジェクト同様Userオブジェクトもattributeプロパティを持っています。これは連想配列で、適当な値をセットし、後ほどその値を他のモジュールで使用するのに便利です。パスポート的な使い方も勿論可能です。
オーセンティケーションの使い方
ログインモジュールの作成 – module.iniの設定
Test同様、modules/Security/config/module.iniを設定します。
[module] ENABLED = "On" NAME = "Security"
ログインモジュールの作成 – テンプレートの作成
まず、ログインのためのモジュールを作成します。
【modules】 【Security】 【actions】 【views】 【templates】
モジュール名は上記で指定したように
Security
とします。
アクション名は
Index
なのでログインフォームのテンプレートは
IndexInput.html
とします。今回はモジュールが複数になるので、templatesディレクトリ以下にSecurityディレクトリを作ってその下にテンプレートを置きます。
【modules】 【Security】 【actions】 【views】 【templates】 【Security】IndexInput.html
実際の内容は以下のようにします。
<form action="index.php?module=Security" method="post"> <input type="text" name="id"> <input type="password" name="pass"> <input type="submit" value="login"> </form> <?= $template['error'] ?>
注目点は、<?= $template[‘error’] ?>の部分です。今回は、IndexError.htmlを作らず、フォーム上にエラーを表示するようにします。
ビューの作成
まずテンプレートのディレクトリをSecurityにします。
class Security_IndexInputView extends PHPView{ public function execute(){ $this->setDirectory( MO_WEBAPP_DIR . '/templates/Security' ); $this->setTemplate( 'IndexInput.html' );
次に、今回はInputがエラー表示も兼ねているので、エラーを取得して表示させる機能が必要です。
$request = $this->getContext()->getRequest(); $this->setAttribute ( 'error', join( "<br>", $request->getErrors() ) ); } }
アクションの作成 – バリデートとエラー
アクションは今までのおさらいとなります。INPUTでフォームを表示し、POSTを渡されたらvalidateでidとpassをチェックし、正しければexecute()を実行します。
idをfoo、passをbarと設定し、バリデートします。
class Security_IndexAction extends Action{ public function validate(){ $flag = true; $request = $this->getContext()->getRequest(); if( $request->getParameter( 'id' ) != 'foo' ){ $request->setError( 'id', 'IDが違います' ); $flag = false; } if( $request->getParameter( 'pass' ) != 'bar' ){ $request->setError( 'pass', 'パスワードが違います' ); $flag = false; } return $flag; }
今回やや違う部分は、setErrorでidとpassというキーにエラーメッセージを設定している部分です。これは、Requestオブジェクトのプロパティのerrorsにここで指定したキーで値を入力している、という意味です。
また、今回はErrorのビューを使わずに、フォーム上にエラーを表示するように、エラーが出てもInputのビューを使うように設定する必要があります。
public function handleError(){ return array( 'Security', 'IndexInput' ); }
handleError()は、エラーが出た場合の挙動を設定し、返り値は通常ビュー名となります。ここで書いてあるようにarray( ‘Security’, ‘IndexInputView’ );とすると、SecurityモジュールのIndexInputビューに飛ばすことができます。
アクションの作成 -execute()
フォームが送信され、POSTで値をを受け取ったらexecute()を実行するように設定します。
public function getRequestMethods(){ return Request::POST; }
execute()内には、このユーザーがログインに成功した、という証明をセッションに記録します。
public function execute(){ $user = $this->getContext()->getUser();
この一文は、セッションの値を保持するUserオブジェクトを取得しています。
$user->setAuthenticated( true );
これでオーセンティケーション(証明)をこのユーザーに与えます。つまり、セッションにこのユーザーがログインした、ということを記録するのです。
$this->getContext()->getController()-> redirect( 'index.php?module=Test' ); } }
この文は、index.php?module=Testに飛ぶ、という意味です。
つまり、ここでしていることは、ログインに成功すると、Testモジュールに飛ぶようにするということです。
アクションの保護
次に、Indexアクションを保護するために、
【modules】 【Test】 【actions】IndexAction.class.php
内に
public function isSecure(){ return true; }
と記述する必要があります。これにより、このアクションはへのアクセスには、まずログインする必要がある、ということを定義します。
オーセンティケーション 結論
index.php?module=Testにアクセスしてみましょう。自動的にindex.php?module=Securityに飛ぶはずです。ここで正確なパスワードを入力すると、Testにアクセスすることが出来ます。
これでこのユーザーはログインしたということがセッションに記録されたので、他の保護されたモジュールにも、自由にアクセスできます。ここでブラウザを閉じたりすると、セッションが切れるので、再びログインし直す必要があります。
クレデンシャルの使い方
クレデンシャル(パスポートのような物)は特定のモジュールにアクセス制限をかけるのに便利な機能です。
ユーザーにクレデンシャルを与えるには、モジュール内のどこでも良いので、
$user->addCredential( 'xxx' );
と書きます。$userは上記のユーザーオブジェクトです。xxxの部分に適当な値を入れて、この特定のアクセス制限に名前をつけます。
次に、制限をかけたいアクション内に
public function getCredential(){ return 'xxx'; }
というメソッドを追加します。ここのxxxは上記のアクセス制限名となります。このメソッドを書いたアクションは、アクセス制限がかかり、xxx‘のクレデンシャルを持っていないユーザーがアクセスできなくなります。
クレデンシャルの他の使い方
例えば、特定のリンクにアクセスさせたくない場合、ハイパーリンクをクレデンシャルで制限することができます。
まず、ビューで、テンプレートにユーザーオブジェクトを渡しておきます。
$user = $this->getContext()->getUser(); $this->setAttribute( 'user', $user );
次に、アクセスを制限するリンクをIF文で囲み、このユーザーがxxxというクレデンシャルを持っているかチェックします。
<? if( $template['user']->getCredential( 'xxx' ) ): ?> <a href="アクセス制限先URL">アクセス制限先</a> <? endif; ?>
これでこのユーザーがxxxというクレデンャルを持っていない限りこのリンクを見ることはできません。
アトリビュートの使い方
Request同様、Userのattributeも
$this->setAttribute( 'キー', '値' );
の形で設定します。
この値はセッションに保存されているので、他のモジュールなどで、
$this->getAttribute( 'キー' );
で取り出す事ができます。