セキュリティ

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_SECURITYONにすることで、ユーザーがログインしているかをアクセスごとにチェックし、ログインしていないユーザーは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でidpassというキーにエラーメッセージを設定している部分です。これは、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( 'キー' );

で取り出す事ができます。

↑ページトップへ戻る