AuthComponent + AclComponent + AclBehavior CakePHP1.2RC2
以下のサイトを参考にして、とりあえず動くものを作ってみた。
- 【CakePHP】AuthComponentについてのまとめ 【ざっくり基本編】
- 【CakePHP】AuthComponentについてのまとめ その2【ちょっとしたコツ編】
- How to use ACL with Cake PHP 1.2.x?
- 5.1.1 Understanding How ACL Works
- Using AuthComponent and ACL in CakePHP 1.2
- Using AclBehavior in CakePHP 1.2
他にもいろいろ見ましたが、調べすぎて覚えてません(;><)
そのままでは、動かないものがあったので、修正したソースをとりあえず公開しておきます。
viewは、scaffoldでいけるものは作ってません。
変なとこがあれば、突っ込んでください!
テーブル
まずは、データベース。Acl関連のテーブルは後でコンソールから作成する。
-- -- テーブルの構造 `groups` -- CREATE TABLE `groups` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) collate utf8_unicode_ci NOT NULL, `parent_id` int(11) default NULL, PRIMARY KEY (`id`), KEY `parent_id` (`parent_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- -------------------------------------------------------- -- -- テーブルの構造 `users` -- CREATE TABLE `users` ( `id` int(11) NOT NULL auto_increment, `username` varchar(255) collate utf8_unicode_ci default NULL, `password` varchar(255) collate utf8_unicode_ci default NULL, `group_id` int(11) NOT NULL, `disabled` tinyint(1) NOT NULL, `created` datetime default NULL, `modified` datetime default NULL, PRIMARY KEY (`id`), KEY `group_id` (`group_id`), KEY `disabled` (`disabled`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
モデル
AclBehaviorは、createの時は役に立ってくれるが、updateの時は役立たず・・・
あと、aliasにも何も入れてくれないので、saveを上書きしてます。
app/models/group.php
<?php class Group extends AppModel { public $actsAs = array('Acl'); function parentNode(){ if (!$this->id) { return null; } $data = $this->read(); if (!$data['Group']['parent_id']){ return null; } else { return array('model' => 'Group', 'foreign_key' => $data['Group']['parent_id']); } } // 更新時に親IDを変更する // この辺の処理おかしいです。下のコメント欄を参照してください。 // 2010-02-28 コメントを受け修正 function save($data = null, $validate = true, $fieldList = array()) { if (parent::save($data, $validate, $fieldList)) { App::import('Component', 'Acl'); $Aro = new Aro; $conditions = array( 'model' => $this->name, 'foreign_key' => $data['Group']['parent_id'], ); $parent_id = $Aro->field('id', $conditions); $conditions = array( 'model' => $this->name, 'foreign_key' => $data['Group']['id'], ); $Aro->id = $Aro->field('id', $conditions); $Aro->saveField('parent_id', $parent_id); $Aro->saveField('alias', $this->name . '::' . $data['Group']['id']); return true; } return false; } } ?>
app/models/user.php
<?php class User extends AppModel { public $actsAs = array('Acl'); public $belongsTo = array('Group'); function parentNode(){ if (!$this->id) { return null; } $data = $this->read(); if (!$data['User']['group_id']){ return null; } else { return array('model' => 'Group', 'foreign_key' => $data['User']['group_id']); } } // 更新時に親IDを変更する // この辺の処理おかしいです。下のコメント欄を参照してください。 // 2010-02-28 コメントを受け修正 function save($data = null, $validate = true, $fieldList = array()) { if (parent::save($data, $validate, $fieldList)) { App::import('Component', 'Acl'); $Aro = new Aro; $conditions = array( 'model' => 'Group', 'foreign_key' => $data['User']['group_id'], ); $parent_id = $Aro->field('id', $conditions); $conditions = array( 'model' => $this->name, 'foreign_key' => $data['User']['id'], ); $Aro->id = $Aro->field('id', $conditions); $Aro->saveField('parent_id', $parent_id); $Aro->saveField('alias', $this->name . '::' . $data['User']['id']); return true; } return false; } } ?>
コントローラ
app/controllers/groups_controller.php
<?php class GroupsController extends AppController { public $scaffold; } ?>
app/controllers/users_controller.php
<?php class UsersController extends AppController { public $scaffold; function login() { } function logout() { $this->Auth->logout(); $this->redirect(array('action' => 'login')); } } ?>
ビュー
ログアウトしたり、メッセージを確認するために以下を追加
app/views/layouts/default.ctp
<?php echo $auth['User']['username']; ?> <?php echo $html->link('Logout', array('controller' => 'users', 'action' => 'logout')); ?> <?php if ($session->check('Message.auth')) { $session->flash('auth'); } ?>
app/views/users/login.ctp
<h2>ログイン</h2> <?php echo $form->create('User', array('action' => 'login')); echo $form->input('username'); echo $form->input('password'); echo $form->end('Login'); ?>
ブラウザで
とりあえず、認証を効かす前にユーザをつくっておく。
http://yourwebroot/groups/index
にアクセスして、「Admin」と「User」くらいをつくっておく。
(parent_id は 0 でいい)
次に
http://yourwebroot/users/index
にアクセスして、「testAdmin」「testUser」なんかをつくっておく。
それぞれ、グループは「Admin」「User」にしとく。
パスワードは暗号化されてないので、コレをいれてAppControllerを書く。
app/controllers/components/no_hash.php
<?php class NoHashComponent extends Object { /** * 暗号化しないでそのまま返す */ function hashPasswords($data){ return $data; } } ?>
app/app_controller.php
<?php class AppController extends Controller { public $components = array('Acl', 'Auth', 'NoHash'); public $publicControllers = array('pages'); function beforeFilter() { if (isset($this->Auth)) { $this->Auth->userScope = array('User.disabled' => 0); $this->Auth->authenticate = $this->NoHash; $this->Auth->loginAction = '/users/login'; $this->Auth->loginRedirect = '/users/index'; $this->Auth->authorize = 'actions'; if (in_array(low($this->params['controller']), $this->publicControllers)) { $this->Auth->allow(); } $this->set('auth', $this->Auth->user()); } } } ?>
で、
http://yourwebroot/users/login
にアクセス、ログインしてみてダメ!って言われればとりあえすOK。
再びコンソールでAcoの登録
cake acl create aco root Users cake acl create aco Users index cake acl create aco Users logout
パーミッションの設定
こんな感じとか
cake acl grant Group.1 Users all
こんな感じとかで登録
cake acl grant User.1 Users/index all
つまり
cake acl grant {model}.{id} {controller}/{action} all
てことです。
ID忘れてしまったら、
cake acl view aro
で以下のように表示される。
Aro tree: --------------------------------------------------------------- [1]Group::1 [7]Group::4 [4]User::1 [5]User::2 [2]Group::2 [8]Group::5 [3]Group::3 [6]User::3 ---------------------------------------------------------------
で、
http://yourwebroot/users/login
にアクセス、権限を与えたユーザでログインしてみてindexが表示されればとりあえすOK。
とりあえず、自分が忘れないうちにバタバタっとまとめてみました。