CakePHPのACLを効率的に管理する


CakePHP Advent Calendar 2011の3日目です。

@kara_dが担当させていただくことになりました。

今回はACLについて書こうと思います

ACLは、僕にとって結構CakePHPを選ぶポイントの1つで、気に入っています。
Play Frameworkにもあればいいのにって思ったりします。

ACLってなんだっけ?って方は、
ACL を制御するシンプルなアプリケーション
このチュートリアルで遊んでみてください。

そうそう、今回の記事はバージョン1.3系の話です。2.0系のACLは使った事がないですが、きっとよいでしょう。

ところで、ACLを結構使っていると言うと、俺も使ってるぜってあまりならないことが多いです。
多くの場合、

  • なんか複雑そうだったのでオレオレACLを使っている
  • そもそもプロジェクトでそういう複雑なパーミッション管理が必要でない

という感じではないでしょうか?

しかしCakePHP標準のACLは非常に便利な上に、使うことで生じるメリットがあります。

  • デフォルトで組み込まれているためメンテされており、安心
  • 既に多くの使用実績があり、なかなか厳格
  • それほど多くはないがノウハウがWeb上にある

ということで、積極的な利用をおすすめしたいです。

ACLの管理をコードでする理由

ACLと一口に言っても、その管理の方法は様々なスタイルがあり、よく使われているものにACLプラグインというのがあります。

Alaxos – CakePHP – Plugin ACL

これは、Webの画面からACLやAROのビルドやパーミッション設定が出来るというものです。非常に便利で、特にパーミッション設定などは、一覧で何が出来てなにが出来ないかを把握するのに役立ちます。
ただし、僕はこのプラグインは限定的に利用するにとどめています。

ACLプラグインは、ACL周りの設定には使用せず、現状のACLがきちんとパーミッション設定されているかの確認のみに使用します。

何故でしょうか?

実は最初の頃ACLの管理にはこのプラグインを使っていました。
しかし、CakePHPを使ったプロジェクトが大きくなるにつれて、複数人数で開発を行うようになり、ACL設定の漏れやマージミスが発生したのです。

そこで、至った結論が、「ACLはコードで管理する」というものでした。

ACLのパーミッションの管理方法について

CakePHPには、ACLの設定をコードで行う事が出来るAPIが用意されています。

例えば、Pagesコントローラーのindexについてアクセス許可をしたい場合、

$this->Acl->allow($group, "controllers/Pages/index");

という書き方で対象のグループに許可を与える事が出来ます。だいたい、僕が使うグループは、管理者グループ、一般ユーザーグループ、特殊ユーザーグループ(プレミア会員など)みたいな感じでユーザーを設定しておいて、それぞれに許可を出します。

アクセスを禁止する場合は、

$this->Acl->deny($group, "controllers/Pages/index");

denyメソッドを使います。

もちろん、これはコントローラー側でACLコンポーネントを使用するという前提の話です。
こういった感じで、各アクションのパーミッション設定をしていきます。
CakePHPでは、プラグインのアクションにもパーミッションが設定できるようになっており、

$this->Acl->allow($group, "controllers/MyCategory/Categories/index");

みたいな書き方でMyCategoryプラグインのCategoriesコントローラーのindexアクションの設定が行えます。

また、

$this->Acl->allow($group, "controllers/Pages");

という書き方をすると、該当コントローラーのパーミッションを一度に設定することも出来ます。

これらを使って、コードとしてコントローラーに書いておくことで、

  • コードとして書かれているため、Gitなどで共有できる
  • 間違いがあった場合、お互いに修正できる
  • 新しい環境での構築が楽

上記のメリットがあります。

効率的な管理

ただし、プロジェクトが進むと、アクションとグループの数が増えて、ACLのコードが膨大になったりします。
1000行超えとかあります。

さて、こういうアクション毎に設定していった大量のACLを整理するにはどうしたらよいでしょうか?
考え方のベースとしては、ACLの一括設定を有効に使っていくというのが考えられます。

スタイルとしては2つで、許可を行うものの一覧を表すホワイトリスト形式と、許可しないものの一覧を列挙するブラックリスト方式です。

ホワイトリスト形式は、こんな感じで、

$this->Acl->deny($group, "controllers/Pages");
$this->Acl->allow($group, "controllers/Pages/about");
$this->Acl->allow($group, "controllers/Pages/test");
$this->Acl->allow($group, "controllers/Pages/contact");

一旦全てを許可しない状態に設定したあと、許可するものを指定していく方式です。
許可するものを視覚化できるので、一般ユーザーなどの管理に使えます。書かなかったアクションは許可されないからです。

ブラックリスト形式は、逆に、

$this->Acl->allow($group, "controllers/Pages");
$this->Acl->deny($group, "controllers/Pages/about");
$this->Acl->deny($group, "controllers/Pages/test");
$this->Acl->deny($group, "controllers/Pages/contact");

こういう風に、全てを許可した上で、禁止するアクションのみを指定していきます。
この方式は管理者ユーザーのような、大多数の部分にはアクセスできるけれど、一般ユーザーの登録みたいなアクセスされるとなんらかの不整合が起きたりするところへ禁止する形に向いています。
ブラックリスト方式の注意点は、新しくアクションが追加されたことを知らずに、ACLを再構築してしまうと、暗黙のうちに許可されてしまう点です。

これらを駆使して、ACLのパーミッションコードを書いていくと、結構縮まります。

ということで、良いACLライフを!!

明日は@shin1x1さんです。よろしくお願いします。

Comments are closed.