ACLによるcontroller/action以外の権限設定

CakePHPACL機能を使って、model(controller)/action以外にアクセス制限をかける方法の検討。

 ちょっと変則ですが、可能そうです。


予定している構成が基本、

controller 
 ┬ PC
 ├ 携帯
 └管理画面

という感じなので、controller/action単位のアクセス制限だけではなく、PC/携帯/管理画面ごと表示モード単位(お勝手仮名)でのアクセス制限がほしい。


最初、acoの設定を
controller/mode/action (Users/mobile/index)のように入れて対応できないかと思いましたが、
authの仕様上、どうもそれは無理っぽい。


と思って諦めかけた時に、以下の記事でひらめき。

http://onlineconsultant.jp/pukiwiki/?Cake%20PHP%20ACL%20%E7%89%B9%E5%AE%9A%E3%81%AE%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%A0%E3%81%91%E7%B7%A8%E9%9B%86%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B
http://d.hatena.ne.jp/roitan/20090102#1230878046


 aco=アクションと、限らなくてもいいんじゃないか?
 ACL情報はapp_controllerレベルでもたぶんチェックできる
 だったら、Auth&ACLでcontroller単位でのチェックを通し、
 しかる後、app_controllerで、mode単位のチェック追加してはどうか?


検討してみました。


ひとまずacoパーミッションは全削除して、思い切りシンプルに作り直し。

mysql> SELECT * FROM acos;
+----+-----------+-------+-------------+-------------+------+------+
| id | parent_id | model | foreign_key | alias       | lft  | rght |
+----+-----------+-------+-------------+-------------+------+------+
|  1 |      NULL |       |        NULL | controllers |    1 |    6 |
|  2 |         1 |       |        NULL | Users       |    2 |    3 |
|  3 |         1 |       |        NULL | Groups      |    4 |    5 |
+----+-----------+-------+-------------+-------------+------+------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM aros_acos;
+----+--------+--------+---------+-------+---------+---------+
| id | aro_id | aco_id | _create | _read | _update | _delete |
+----+--------+--------+---------+-------+---------+---------+
|  1 |      4 |      2 | 1       | 1     | 1       | 1       |
+----+--------+--------+---------+-------+---------+---------+
1 row in set (0.01 sec)

これで、Users::4の一般メンバーグループは、

controller アクセス
users
admin/users
admin/groups*1 ×

 の状態に。


ここでacosに以下追加。

[cake@cake console]$ ./cake acl create aco root prefix
[cake@cake console]$ ./cake acl create aco prefix pc
[cake@cake console]$ ./cake acl create aco prefix m

Aco tree:
---------------------------------------------------------------
  [1]controllers

    [2]Users

    [3]Groups

  [4]prefix

    [5]pc

    [6]m

    [7]admin

---------------------------------------------------------------

[cake@cake console]$ ./cake acl deny Group::4 admin all
[cake@cake console]$ ./cake acl grant Group::4 pc all
[cake@cake console]$ ./cake acl grant Group::4 m all

mysql> SELECT * FROM aros_acos;
+----+--------+--------+---------+-------+---------+---------+
| id | aro_id | aco_id | _create | _read | _update | _delete |
+----+--------+--------+---------+-------+---------+---------+
|  1 |      4 |      2 | 1       | 1     | 1       | 1       |
|  2 |      4 |      7 | -1      | -1    | -1      | -1      |
|  3 |      4 |      5 | 1       | 1     | 1       | 1       |
|  4 |      4 |      6 | 1       | 1     | 1       | 1       |
+----+--------+--------+---------+-------+---------+---------+
4 rows in set (0.00 sec)

そして試しに、app_controllerのbeforeRenderで、以下を出力してみた。

コード 結果
$this->Acl->check($this->AuthPlus->user(), 'pc') true
$this->Acl->check($this->AuthPlus->user(), 'm') true
$this->Acl->check($this->AuthPlus->user(), 'admin') false
$this->Acl->check($this->AuthPlus->user(), '') false


・・・・できる!


管理画面のprefixがadminじゃなくてConfigure::read('Routing.admin')だとか、
他全般の設計しなおしますが、

手法としてこれ可能そうです*2


そして、contoller/action、model(仮名)の他のものへも応用可能なはず・・・・

*1:一般ユーザ側のgroupsは、なし

*2:負荷などについては、置いておいて。。