CakePHP 1.2のAuthコンポーネントを利用してユーザグループ毎にアクセスコントロールをする方法

標準

Authコンポーネントを利用して、ユーザグループごとに利用できるアクションを割り当てる方法をご紹介します。
※簡易ACLって感じで。

できること

  • ユーザグループごとに各アクションの利用可否を設定
  • アクションの認可情報は、コントローラ内に記述
  • 認証ユーザごとにログイン後の遷移先を変更(おまけ2)

(この方法、どこかの記事を参考にさせていただいたのですが参考元がわからなくなりました。。)

ここで紹介したソースをまとめたものはこちら

GroupテーブルとUserテーブルはいたって普通にこんな感じ。

userモデルは、blongToを付け加えてgroupを引っ張ってこれるようにしておきます。

app_controller.phpに、beforeFilter、isAuthorizedメソッドを追加します。

AppController::beforeFilter()ではAuthComponentのパラーメータを調節し、adminルーティングが行われている場合は、管理ページ側レイアウトへ変更するようにしています。

AppController::isAuthorized()では、認証されたユーザのグループと各アクションに割り振られた権限を比較してアクセスコントロールを行います。

各アクションが、どのユーザグループで利用可能かを定義するため、AppController::$permissions変数を追加しています。各コントローラではこの変数をオーバライドして、ユーザグループごとにアクションの利用を許可します。

ログイン処理を行う、UsersControllerはこんな感じ。

UsersController::beforeFileter()で、ログインアクションが呼ばれた際に、Authコンポーネントの自動リダイレクト処理をキャンセルするよう指示し、リダイレクト処理はログインアクション中(今回は、UsersController::_login())で行うようにしておきます。

また、通常、Admin共通のログイン処理メソッド、UsersController::_login()を作成してそこで、Authセッションにグループ名を追加する処理を行います。

おまけ:
この方法で、Controller::$permissionsの設定を簡便化するために、config/acl.phpを作成してユーザグループのグループを作っておくとちょっと幸せになるかもしれません。

作成したら、config/bootstrap.phpに以下を追記して読み込み。

おまけ2:
UsersController::beforeFileter()で、

としておくと、認証時に自動リダイレクトされなくなるので、UsersController::login()でログイン後の遷移先を変更できます。(例えば、グループを見てadminの場合は遷移先を/admin/にするとか。

7 Comments

  1. こんにちは!拝見させていただき、大変ためになりました。
    私の場合はgroupではなく、usersに種別を持たせた形を考えていたのですが、ここも柔軟に対応できる形になっていたので参考にさせていただいています。
    一点、確認なのですが

    ・ユーザー一覧:管理者と、一般ユーザ
    ・ユーザー編集:管理者のみ
    のように権限を設定した場合、一般ユーザが一覧→編集に遷移した際には(リンク続きなので)エラーがでるのですが、まったく違うコントローラーから、URLを時下打ちし、users/edit/5などに遷移した場合にはどのようにするのがベストなのでしょうか。isAuthorized内でfalseで返すタイミングで、どこかのエラーページにリダイレクトするのが望ましいのでしょうか。(現在はそうしています)

    エラーを出す文字列が自画面なので、URLじか打ちで権限に引っかかった場合、その画面でエラーを出力しようとするのでどうも無限ループになっているのです。(私の書き方がまずいのかな・・)今はisAuthorized内でfalse遷移の場合に特定のページにリダイレクトしています。
    isAuthorized以外で「認証に失敗した」事を取得できるタイミングは他にないようなのでここに書くのが正攻法ということでしょうか。

    教えていただき、さらに質問してすみません。気になってしまったので質問させていただきました。回答していただけたらうれしいです。

    • yashioさま >

      通常ですとisAuthorized()からfalseが返ってきた場合、Authコンポーネントは、refererを参照して遷移前のページに戻ります。
      また、Session::setFlash()で、セッションにauthErrorのメッセージを書き込みます。(このセットされたメッセージはビューで、$session->flash(‘auth’);とすれば表示されます。)

      特定のエラーページに遷移させたいということであれば、おっしゃるとおり、isAuthorized内でリダイレクト処理をかけるのがベストでしょうね。(Controller::beforeFilterでセッションのMessage.authをチェックする方法もあります。)

      おすすめだと思うAuthエラー処理は、Controller::flash()メソッドを利用してログイン後のページにリダイレクトでしょうか。

  2. nojimage 様
    お返事ありがとうございます。
    つまり、URLを直接指定して遷移した場合はrefererを参照し、遷移前のURLに戻り、エラーメッセージを出すという事なのですね。
    私の場合は、なぜかFireFoxで「ループしています」というメッセージがでるので、うまく参照できていないきがします。(正常動作だとエラーメッセージをrefererで取得した画面で表示すると推測します)

    ログイン後のページにリダイレクトというのも方法としてありますね。検討してみます。とにかく非常に参考にさせていただきました。ありがとうございました。

  3. Pingback: matya's diary - ユーザグループ管理

  4. こんにちは!!

    cakephpでWebアプリを作成しているものです。
    ACLについて何かいい情報はないかと模索中に当サイトを拝見致しました。
    非常にわかりやすく参考にさせていただきましたが
    1点だけ確認したいことがありましてコメント致しました。

    authコンポーネントのデフォルト利用テーブルのusersから
    他テーブルに変更する際は
    $this->Auth->userModel = ‘モデル名’;
    で変更しますが、この記述をusers_controllerのbeforefilter()に追加したら
    authコンポーネントが使えなくなりました。
    現象としてはわざと違ったID、Passでログインしようとしても
    エラーメッセージが表示されず、authコンポーネントが利用されていないイメージです。

    何か特別な設定方法があるのでしょうか。
    ご返答頂けると幸いです。

    以上

    • $this->Auth->userModel = 'モデル名';

      の記述は、UsersControllerではなく、AppController::beforeFilter()に記述します。

      ただし、この場合上記コードのモデル名やコントローラ名など色々と変更しなければなりませんので、そのあたりもお忘れなく。

      テーブル名だけを変更したいのであれば、以下のようにUser::$useTableを変更するのが1番簡単かと思います。

  5. nojimage様

    お世話になります。
    ご返答ありがとうございます。

    さっそく試してみたいと思います。
    何か判明次第、ご報告致します。

    以上

コメントを残す

Page optimized by WP Minify WordPress Plugin