cakephp-auth-CtpAndACL

CakePHP 内の固定ページに対するアクセスコントロール

CakePHP には AuthComponent や AclComponent といったコア・コンポーネントによってパワフルな認証およびアクセスコントロールの機能が提供されています。

自分はこれを使い始めたとき、リダイレクトループにはまったり、「About us」や「はじめての方へ」といった固定のコンテンツもアクセスできなくなったり・・と少しだけハマったので対策メモを残します。

ホームと固定ページは PagesController を介して表示している

自分で controller や view を用意しなくても CakePHP のトップページは表示されます。これは CakePHP のコア部分にある pages_controller.php(PagesController クラス) と home.ctp が表示しているものです。「About us」や「はじめての方へ」といった固定コンテンツも、この PagesController を使って、View となる ctp ファイルだけ自分で作るのが一般的です。

この PagesController へのアクセス権がないと、ログイン後に固定ページを見に行くとリダイレクトループにハマることがよくあります。

プラン1:全ての固定ページを認証なしで見えるようにする

固定ページの内容はユーザ登録前でも見せたいという事が多い気がします。固定ページは認証不要と割り切れるのであれば以下のコードを app_controller::beforeFilter に追加します。

$this->Auth->allow(array('controller' => 'pages', 'action' => 'display'));

これでどの .ctp ファイルで定義されている固定ページも未認証ユーザでも表示できるようになります。

プラン2:特定のページだけは認証なしで見えるようにする

特定のページで認証不要な場合も app_controller:beforeFilter  内で allow メソッドを使います。例えば、ホームと About us のページは誰でも見えるようにしたいという場合はこんな感じです。(About us の内容は views/aboutus.ctp として作成済みだと仮定します)

// ホームと About us に誰でもアクセス可能
$this->Auth->allow(array('controller' => 'pages', 'action' => 'display', 'home'));
$this->Auth->allow(array('controller' => 'pages', 'action' => 'display', 'aboutus'));

プラン3:特定のグループにだけ固定ページへのアクセスを許可する

※この場合も、プラン2の方法で home へのアクセス許可は設定しておかないと、パーミッションエラー時にリダイレクトループに陥ります。

ACL の制限テーブルの中に固定ページを含めて特定のグループまたはユーザにだけ固定ページのアクセスを許可することができます。コマンドラインから設定します。

※前提条件

  • root / controllers が ACO に登録済み
  • 任意のグループ Groups/Group.1 が ARO に登録済み

1. PagesController::display を ACO に登録
[cakephp installed dir]/cake/console/cake acl create aco  controllers Pages
[cakephp installed dir]/cake/console/cake acl create aco  controllers/Pages display

2. Group.1 に全固定ページへのアクセス権を与える
[cakephp installed dir]/cake/console/cake acl grant Group.1 controllers/Pages/display all

プラン4:グループごとに表示可能な固定ページを設定する

ACLを使うと、アクション(ここで言う PagesController::display)まではグループまたはユーザ単位で設定できるのですが、’home’, ‘about us’ などのパラメータまでを管理できないみたいです。

細かい設定は AppController::beforeFilter でユーザIDや、そのユーザに紐づくグループIDを引いて来て if 文などで allow, deny をコールするか、独自にコントローラにアクション(メソッド)を作って各メソッドの中でそれぞれ別の固定ページにリダイレクトすればアクション単位での制御が可能になるかな。