たきゃはしです

Webとかデザインとかプログラムとか

CakePHP2でACLを超簡単管理できるプラグイン「ACL Plugin 2」

2013/01/17 更新


CakePHP2.0ではACL関連のチュートリアルが充実。プラグインと併せて簡単な導入&便利な管理機能を

 →ACL Plugin for CakePHP 2.0

Plugin ACLがCake2に対応している事をツイッターで知りました。(良いフォロワーのツイートはなぜこんなにも素晴らしいのか・・・)

しかし、チュートリアルが充実したといっても実際のところACL関連はまだまだ情報が少ないです。一度使ったことがあるプラグインという事もあり今回も記事にしてみました。

はじめに

今回は管理者・運営者・一般ユーザという3つのグループ(ロール)をもとにACL機能を実装してみたいと思います。Blogsコントローラを作成し、CRUDへアクセス権限を設定します。

  • 管理者:CRUDを許可
  • 運営者:CRUを許可
  • ユーザ:Rを許可

ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(コピペです)
  • プラグインのパラメータの設定(コピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

以上です。また、Cakeの基本設定については省略しています。

ダウンロードとインストール

  • インストール
    • ダウンロードしたファイルをAclフォルダに解凍
    • app/Plugin/ 以下に解凍したAclフォルダをそのまま配置

・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

prefixルーティングの設定

「app/Config/core.php」113行目あたり

Configure::write('Routing.prefixes', array('admin'));

・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

データベーススキーマの作成

「cake2-test」というデータベースを作成します。
続いて、以下のSQLをコピペで実行してください

CREATE TABLE `acos` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `parent_id` int(10) DEFAULT NULL,
  `model` varchar(255) DEFAULT '',
  `foreign_key` int(10) unsigned DEFAULT NULL,
  `alias` varchar(255) DEFAULT '',
  `lft` int(10) DEFAULT NULL,
  `rght` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


CREATE TABLE `aros` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `parent_id` int(10) DEFAULT NULL,
  `model` varchar(255) DEFAULT '',
  `foreign_key` int(10) unsigned DEFAULT NULL,
  `alias` varchar(255) DEFAULT '',
  `lft` int(10) DEFAULT NULL,
  `rght` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


CREATE TABLE `aros_acos` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `aro_id` int(10) unsigned NOT NULL,
  `aco_id` int(10) unsigned NOT NULL,
  `_create` char(2) NOT NULL DEFAULT '0',
  `_read` char(2) NOT NULL DEFAULT '0',
  `_update` char(2) NOT NULL DEFAULT '0',
  `_delete` char(2) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;


CREATE TABLE `blogs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `body` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;


CREATE TABLE `groups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;


CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `group_id` int(11) NOT NULL,
  `username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;

ACLのテーブルだけを作りたい場合は、コマンドですぐに出来ます。

cd app/Console
./cake acl initdb
n
y


・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

プラグインのパラメータの設定

「Plugin ACL」プラグインの設定となります。

まず、「app/Config/bootstrap.php」をオープンし、末尾に以下の記述します。

CakePlugin::load('Acl', array('bootstrap' => true));

さらに「app/Plugin/Acl/Config/bootstrap.php」のソースを全てコピーし、続けてペーストします。ただのコピペですね。

環境に合わせてパラメータを変更します。

通常「Role」とするモデルを「Group」にしたので変更します

Configure :: write('acl.aro.role.model', 'Group');

通常「role_id」とする外部キーを「group_id」にしたので変更します

Configure :: write('acl.aro.role.foreign_key', 'group_id');

・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

Group・User・BlogのMVCを作成

ここがおそらく一番複雑な工程です。複雑なだけで難しくはないんです。安心してください。説明は長くなると思いますが・・・(;´Д`)なるべく手短にします

Bakeで基本のMVCを出力

Bakeの使い方については、1つの記事になってしまうので割愛します。要点のみ書きます。

まずはじめに注意事項を説明します!

  • Scaffoldは使っちゃダメ!ACLで使うと必ずおかしくなります!
  • ここではヘルパー、コンポーネントは設定しないでください!

アソシエーションは以下になります。

  • Group hasMany User
  • User hasMany Blog
  • User belongsTo Group
  • Blog belongsTo User
ログイン機能の実装

手短にコピペで

「app/Controller/UsersController.php

    public function admin_login() {
        if ($this->request->is('post')) {
            if ($this->Auth->login()) {
                $this->redirect($this->Auth->redirect());
            } else {
                $this->Session->setFlash('Your username or password was incorrect.');
            }
        }
    }

    public function logout() {
        $this->Auth->logout();
    }

「app/View/Users/login.ctp」

<?php
echo $this->Form->create('User', array('action' => 'login'));
echo $this->Form->inputs(array(
    'legend' => __('Login'),
    'username',
    'password'
));
echo $this->Form->end('Login');
DBに登録するパスワードをハッシュ化する

「app/Model/User.php

App::uses('AppModel', 'Model');
App::uses('AuthComponent', 'Controller/Component');

class User extends AppModel {

	// 他のコード。

    public function beforeSave() {
        $this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
        return true;
    }
}
AppControllerの設定

ここでコンポーネントやログインの設定を行います。
またAppControllerの場所が「app/app_controllers.php」ではなく「app/Controller/」変更しましたので、特に1.3系の経験者はご注意ください。

「app/Controller/AppController.php

<?php
App::uses('Controller', 'Controller');

class AppController extends Controller {

    public $components = array(
        'Acl',
        'Auth' => array(
            'authorize' => array(
                'Actions' => array('actionPath' => 'controllers')
            )
        ),
        'Session'
    );
    public $helpers = array('Html', 'Form', 'Session');

    public function beforeFilter() {
        //AuthComponentの設定
        $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
        $this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
        $this->Auth->loginRedirect = array('controller' => 'blogs', 'action' => 'admin_add');
    }

}
リクエスタとしてビヘイビアに設定

AclBehaviorを利用するとモデルとACLの関連が自動的に処理されます。
ビヘイビアの利用に伴い、モデルにいくつかの追加を施します。

「app/Model/User.php」に追加

    public $actsAs = array('Acl' => array('type' => 'requester'));

    public function parentNode() {
        if (!$this->id && empty($this->data)) {
            return null;
        }
        if (isset($this->data['User']['group_id'])) {
            $groupId = $this->data['User']['group_id'];
        } else {
            $groupId = $this->field('group_id');
        }
        if (!$groupId) {
            return null;
        } else {
            return array('Group' => array('id' => $groupId));
        }
    }


「app/Model/AppModel.php」に追加

    public $actsAs = array('Acl' => array('type' => 'requester'));

    public function parentNode() {
        return null;
    }
パーミッションをグループのみに単純化する

ACLによるAROのチェックをグループのみにします。

「app/Model/User.php」に追加

function bindNode($user) {
    return array('model' => 'Group', 'foreign_key' => $user['User']['group_id']);
}

※これ追加するだけで出来るらしいけど、なぜかうまくいかないんですよねー。特に問題はないからいいんですが(;´Д`)誰かおしえてください、あーモヤモヤする

・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

グループ&ユーザを追加(AROの追加)

追加の前にAuthによる認証を一時的に解消します。
以下のコードをユーザとグループのコントローラにそれぞれ追加してください。

「app/Controller/UsersController.php」と「app/Controller/GroupsController.php」に追加

function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->allow('*');
}

次にBakeで焼いたフォームにアクセスし、グループ→ユーザの順番で追加してください。
グループ:administrators、managers、users
ユーザ :adminuser、manageuser、useruser

無事AROが登録されたら、一時的に追加した上記のソースはコメントアウトしておきましょう。AROがうまく行けば、お次はACOの追加です。

・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

コントローラ&アクションの追加(ACOの追加)

いよいよ「Plugin ACL」の出番です!!
もう終盤です!あともう少しお付き合い願います(^_^;)

「/admin/acl/acos」にアクセスします。


こんな画面になりましたか?

このページではACLに関する様々な管理が出来ます。
ACOの追加(同期)機能もそのうちの1つです。

早速「Synchronize actions ACOs」をクリックします。すると「Missing ACOs」という見出しと共に大量のリストが表示されると思います。まだ登録されてないACOがあるよ〜(*_*)という状態です。

そのまま下にスクロールすると「Synchronize」というリンクがありますのでクリック。これでACOが最新のデータと同期します。もし、追加機能で新たにコントローラやアクション増えた場合は同様の操作を行います。

これでACOの追加は完了です。

・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)

アクセス権限を設定(AroAcoの設定)

さて、ついに最終章となりACLについてレベルがアップされていると思います。
ここを熟せばとりあえずACL管理には苦労しないと思います。

「/admin/acl/aros/ajax_role_permissions」にアクセスします。

このページではアクセス許可の設定が視覚的に行えます。また、Ajax対応なのでページ遷移なしのリアルタイムで変更できますね。素晴らしい


ここで、はじめに説明したお題を思い出してください。

今回は管理者・運営者・一般ユーザという3つのグループ(ロール)をもとにACL機能を実装してみたいと思います。Blogsコントローラを作成し、よくあるCRUDに対してアクセス権限を与えます。

  • 管理者:CRUDを許可
  • 運営者:CRUを許可
  • ユーザ:Rを許可

それでは上記の通り設定してみましょう。

管理者の許可設定

まず「grant access to all actions」列の「administrators」行にあるチェックマークをクリックしてOKしてみましょう。すると・・・

はい、これで管理者は全てのコントローラ&アクションを許可されました。

  • 管理者:CRUDを許可
  • 運営者:CRUを許可
  • ユーザ:Rを許可

次は運営者の許可設定です。

運営者の許可設定

運営者はCRUを許可するようにしますので、「managers」列にある

  • Blogs->admin_add
  • Blogs->admin_edit
  • Blogs->admin_index
  • Blogs->admin_view

の行にあるチェックマークをクリックします。


これでdeleteだけは許可しない設定になりました。(許可するしないの話をすると、イルーゾォを思いますねw)

  • 管理者:CRUDを許可
  • 運営者:CRUを許可
  • ユーザ:Rを許可
ユーザの許可設定

最後にユーザです。

「Rを許可」とはindexとviewのみアクセスできるという意味ですので「users」列にある

  • Blogs->admin_index
  • Blogs->admin_view

の行をチェックします。

以上です。

・ToDoリスト

  • ダウンロードとインストール
  • prefixルーティングの設定(コピペです)
  • データベーススキーマの作成(ほぼコピペです)
  • プラグインのパラメータの設定(ほぼコピペです)
  • Group・User・BlogのMVCを作成
  • グループ&ユーザを追加(AROの追加)
  • コントローラ&アクションの追加(ACOの追加)(ACOの追加)
  • アクセス権限を設定(ARO_ACOの設定)


ToDoリストもすべて埋まりましたね。

ACLはユーザ単位でアクセス権限を設定するケースやグループの変更が激しいケースでは非常に強い味方になるでしょうね。普通はグループ単位で管理するので、プレフィックスでルーティングするなど別の手段を取っても良いと思います。

セットアップやらここまでやっといてプラグインの使い方は解説しないのかよ!という怒りのブコメが出た場合は少し考えます。まぁ、ACL実装するリテラシがある方なら大丈夫だと思いますけど。笑

それでは、これにて「Plugin ACL」のまとめを終わります。


CakePHP1.3の場合は以下の記事へどうぞ〜
 →CakePHP - ACLの権限管理を超簡単にするプラグイン『Plugin ACL』 - 高橋です