CakePHP に アクセスコントロール を導入する

CakePHP

CakePHPでACLを導入する。

Webサービスを企画した時に、各ユーザー個別にサービスの提供を考えるケースがほぼ大半を占めると思います。(少なくても私の企画環境はそんな感じです)

なので、CakePHPで、それぞれのユーザに応じて各種機能にアクセス権を設定するためのコンポーネント、「ACL – アクセス制御リスト(Access Control List)」の導入です。

参考サイト

ACLを制御するシンプルなアプリケーション — CakePHP Cookbook v2.x documentation.

CakePHP2でACLが超簡単に管理できるプラグイン「Alaxos – Plugin ACL 2.0」まとめ – 高橋です.

CakePHP ACL – アクセス制御リストを攻略する | hijiriworld Web.

CakePHPでACLを実装する際のメモ

CakePHPで行うアクセス制御

Authコンポーネントは、ユーザ認証を実現する非常にシンプルで簡単なコンポーネントですが、あくまでも「そのユーザがログインしているか否か」ということのみです。
それぞれのユーザに応じて各種機能にアクセス権を設定するためのコンポーネント、それが「ACL – アクセス制御リスト(Access Control List)」です。

なので、ウェブサービスで、それぞれの訪問ユーザーのレベルに応じた動きをサイトにさせるためには、どうやら必修の機能のようです。頑張って設定してみましょう。

開発中のシステムと混じってしまうのもなんですし、ここは新規なcakePHPの環境を用意します。 CakePHP2.2.2 CakePHP2.2.5 CakePHP2.3.1で動作を確認しました。

データベースの設定

まずは、ユーザーとグループのテーブルを作ります。

CREATE TABLE users (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password CHAR(40) NOT NULL,
group_id INT(11) NOT NULL,
created DATETIME,
modified DATETIME
) DEFAULT CHARSET=utf8;

CREATE TABLE groups (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
created DATETIME,
modified DATETIME
) DEFAULT CHARSET=utf8;

次に、app/Config/Schema/db_acl.sqlのテーブル作成します。

CREATE TABLE acos (
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INTEGER(10) DEFAULT NULL,
model VARCHAR(255) DEFAULT '',
foreign_key INTEGER(10) UNSIGNED DEFAULT NULL,
alias VARCHAR(255) DEFAULT '',
lft INTEGER(10) DEFAULT NULL,
rght INTEGER(10) DEFAULT NULL,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;

CREATE TABLE aros_acos (
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
aro_id INTEGER(10) UNSIGNED NOT NULL,
aco_id INTEGER(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)
) DEFAULT CHARSET=utf8;

CREATE TABLE aros (
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INTEGER(10) DEFAULT NULL,
model VARCHAR(255) DEFAULT '',
foreign_key INTEGER(10) UNSIGNED DEFAULT NULL,
alias VARCHAR(255) DEFAULT '',
lft INTEGER(10) DEFAULT NULL,
rght INTEGER(10) DEFAULT NULL,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;

DEFAULT CHARSET=utf8 は、2バイト圏のおまじないです。

cake bake します

CakePHPのディレクトリまで降りて、


$cd /path/to/cakephp/
$sudo ./app/Console/cake bake
Welcome to CakePHP v2.2.5 Console
---------------------------------------------------------------
App : app
Path: /Users/gworks/Sites-Folder/cakephp_acl/app/
---------------------------------------------------------------
Interactive Bake Shell
---------------------------------------------------------------
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[F]ixture
[T]est case
[Q]uit
What would you like to Bake? (D/M/V/C/P/F/T/Q)
> m
---------------------------------------------------------------
Bake Model
Path: /Users/gworks/Sites-Folder/cakephp_acl/app/Model/
---------------------------------------------------------------
Use Database Config: (default/test)
[default] >
Possible Models based on your current database:
1. Aco
2. Aro
3. ArosAco
4. Group
5. User
Enter a number from the list above,
type in the name of another model, or 'q' to exit
[q] > 5
A displayField could not be automatically detected
would you like to choose one? (y/n)
> n
Would you like to supply validation criteria
for the fields in your model? (y/n)
[y] > n
Would you like to define model associations
(hasMany, hasOne, belongsTo, etc.)? (y/n)
[y] > y
One moment while the associations are detected.
---------------------------------------------------------------
Please confirm the following associations:
---------------------------------------------------------------
User belongsTo Group? (y/n)
[y] >
Would you like to define some additional model associations? (y/n)
[n] >

---------------------------------------------------------------
The following Model will be created:
---------------------------------------------------------------
Name: User
DB Table: `cakephp_acl`.`users`
Associations:
User belongsTo Group
---------------------------------------------------------------
Look okay? (y/n)
[y] >

Baking model class for User...

File `/Users/gworks/Sites-Folder/cakephp_acl/app/Model/User.php` exists
Do you want to overwrite? (y/n/q)
[n] > y
Wrote `/Users/gworks/Sites-Folder/cakephp_acl/app/Model/User.php`
PHPUnit is not installed. Do you want to bake unit test files anyway? (y/n)
[y] > n
---------------------------------------------------------------
Interactive Bake Shell
---------------------------------------------------------------
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[F]ixture
[T]est case
[Q]uit
What would you like to Bake? (D/M/V/C/P/F/T/Q)
> m
---------------------------------------------------------------
Bake Model
Path: /Users/gworks/Sites-Folder/cakephp_acl/app/Model/
---------------------------------------------------------------
Possible Models based on your current database:
1. Aco
2. Aro
3. ArosAco
4. Group
5. User
Enter a number from the list above,
type in the name of another model, or 'q' to exit
[q] > 4
Would you like to supply validation criteria
for the fields in your model? (y/n)
[y] > n
Would you like to define model associations
(hasMany, hasOne, belongsTo, etc.)? (y/n)
[y] >
One moment while the associations are detected.
---------------------------------------------------------------
Please confirm the following associations:
---------------------------------------------------------------
Group hasMany User? (y/n)
[y] >
Would you like to define some additional model associations? (y/n)
[n] >

---------------------------------------------------------------
The following Model will be created:
---------------------------------------------------------------
Name: Group
DB Table: `cakephp_acl`.`groups`
Associations:
Group hasMany User
---------------------------------------------------------------
Look okay? (y/n)
[y] >

Baking model class for Group...

File `/Users/gworks/Sites-Folder/cakephp_acl/app/Model/Group.php` exists
Do you want to overwrite? (y/n/q)
[n] > y
Wrote `/Users/gworks/Sites-Folder/cakephp_acl/app/Model/Group.php`
PHPUnit is not installed. Do you want to bake unit test files anyway? (y/n)
[y] > n
---------------------------------------------------------------
Interactive Bake Shell
---------------------------------------------------------------
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[F]ixture
[T]est case
[Q]uit
What would you like to Bake? (D/M/V/C/P/F/T/Q)
> q

という感じで、groupとuserについてmodel,controller,viewをbakeします。

リクエスタとして振舞う

モデル中で parentNode() を定義します。こうすることで、AclBehavior でモデルとACLテーブルを自動的に結びつけることができます。

User.php


class User extends AppModel {
public $name = 'User';
public $belongsTo = array('Group');
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));
}
}
}

 

 

Group.php


class Group extends AppModel {
public $actsAs = array('Acl' => array('type' => 'requester'));

public function parentNode() {
return null;
}
}

このコードで、 Group モデルと User モデルをACLに結びつけ、 UserGroup をデータベースに登録した時、常にCakePHPが aros にも同様の登録を行うようにしています。 これにより、 users および groups テーブルをAROと透過的に結びつけるACLの管理機能を、アプリケーションの一部として作成できました。 ユーザーやグループを作成したり削除すると、常に ARO のテーブルも更新されます。

グループとユーザを追加

http://localhost/cakephp_acl/groupsにアクセスします。

bakeしたので、できている画面で、追加ができます。groups/add からグループを追加してみます。

  • administrators
  • managers
  • users

を追加しました。

動作確認も兼ねていくつかユーザーも追加しておきます。

ユーザーとグループを追加すると、arosテーブルに自動で値が追加されていれば、ここまでは成功です。

プラグイン「Plugin ACL」の導入

ACL Plugin for CakePHP 2.0 からプラグインをダウンロードします。

解凍してできたフォルダ acl を /app/plugins に保存します。

app/plugins/acl/config/bootstrap.phpのデフォルトグループがRoleなのでGroupに変更します。

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

 

/app/Config/core.php の admin root を有効にします。

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

/app/Config/bootstrap.php に ACLプラグインのbootstrapを読みこませる指示を追加します。

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

AppController.php の追加

bakeしたAppController.phpに以下を追加しておきます。


class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);

public $helpers = array('Html', 'Form', 'Session');

function beforeFilter() {

// Allow all actions. CakePHP 2.0
$this->Auth->allow('*');

// Allow all actions. CakePHP 2.1
$this->Auth->allow();

//AuthComponentの設定
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'posts', 'action' => 'add');

$this->Auth->actionPath = 'controllers/';

}
}

いよいよ起動です。

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

01

こんなかんじに出てくればOKです。

05【Permissions】【 Roles permissions】で、各グループ毎のアクセス設定ができます。
チェックやバツのアイコンをクリックすると切り替わり、アクセス設定が変更できるようになります。

非常に素敵です。

最後に、ログインアクセスを有効にしておきます。
AppController.php


// Allow all actions. CakePHP 2.0
//$this->Auth->allow('*');

// Allow all actions. CakePHP 2.1
//$this->Auth->allow();

これで、きっと少し楽になるはずです。

コメント

タイトルとURLをコピーしました