[PHP] Ethnaでユーザ権限ごとのアクセス許可を一括管理する

Ethnaでアクセス制限をする場合、一般的にActionクラスのauthenticate()メソッドを使います。
アクション数が多くなってくると、個別に書くのは面倒なので、継承を駆使する場合が多いと思います。
しかしそれでも、ユーザ権限が何種類もあると、管理が煩雑になってしまいます。

今回は、ユーザ権限ごとのアクセス許可を一元管理する方法を紹介します。

手順

まず、ユーザ種別はdefineしてあるものとします。

define(‘USER_TYPE_ANONYMOUS’, 0);
define(‘USER_TYPE_GUEST’,     1);
define(‘USER_TYPE_MEMBER’,    2);
define(‘USER_TYPE_ADMIN’,     3);

次に、ユーザ種別ごとのアクセス許可を、適当なファイルにグローバル変数で記述します。

グローバル変数にするメリットは、index.phpからControllerを生成する前に読み込めるため、BASIC認証と連動しやすい点です。
このアクセス許可一覧変数では、ユーザ種別定数をキーに、アクセス許可するアクション名一覧の配列を値にします。

require_once ‘Appid_Const.php’; //USER_TYPE_*をdefineしてあるファイルをrequire
/**
* 権限毎のアクセス可能アクション一覧
* アクション名の最後の1文字のみ、ワイルドカードとして*(アスタリスク)を使える
*/
$accept_action_list = array(
    USER_TYPE_ADMIN =< array(
        ‘*’,
    ),
    USER_TYPE_MEMBER =< array(
        ‘entry_*’,
        ‘comment_*’,
        ‘inquiry_*’,
    ),
    USER_TYPE_GUEST =< array(
        ‘comment_*’,
        ‘inquiry_*’,
    ),
    USER_TYPE_ANONYMOUS =< array(
        ‘index’,
        ‘help’,
    ),
);

また、Appid_Sessionには、getUserType()というメソッドを作り、ユーザ種別を取得できるようにしておきます。

そして、以下のメソッドを、Appid_ActionClassに入れます。

/**
* このアクションにアクセスできるかどうか調べる
* @return アクセスできるときtrue, 出来ないときfalse
*/
function _authenticate()
{
    global $accept_action_list;

    $controller =& $this->backend->getController();
    if ($controller->_isAcceptableActionName($controller->getCurrentActionName(), $accept_action_list[USER_TYPE_ANONYMOUS])) {
        //ログインなしでアクセスできるアクションの場合
        return true;
    } else if ($this->session->isStart()) {
        $userType = $this->session->getUserType(); //現在の権限を取得
        if (is_null($userType)) {
         $this->ae->add(null, ‘ログインしていません’);
         return false;
        }

        $list = $accept_action_list[$userType]; //現在の権限でアクセスできるアクション
        if (!$controller->_isAcceptableActionName($controller->getCurrentActionName(), $list)) {
            $this->ae->add(null, ‘権限がありません’);
            return false;
        } else {
            return true; //認証された
        }
    } else {
        $this->ae->add(null, ‘ログインしていません’);
        return false;
    }
}

あとは、authenticate()メソッドで

function authenticate()
{
    if ($this->_authenticate() === true)
    {
        return null;
    }
    return ‘index’; //ログイン画面へ飛ばす
}

とすれば完了です。

全アクションの許可・拒否を一括管理できるので、漏れが無くて安心です。

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

baba

ゆとりプログラマー。 高校時代から趣味でプログラミングを初め、そのままコードを書き続けて現在に至る。慶應義塾大学環境情報学部(SFC)卒業。BPS設立初期に在学中から参加している最古参メンバーの一人。Ruby on Rails、PHP、Androidアプリ、Windows/Macアプリ、超縦書の開発などを気まぐれにやる。軽度の資格マニアで、情報処理技術者試験(16区分17回 + 情報処理安全確保支援士試験)、技術士(情報工学部門)、Ruby Programmer Gold、AWSソリューションアーキテクト(アソシエイト)、日商簿記2級、漢検準1級などを保有。

babaの書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ

BPSアドベントカレンダー