【ご注意!】
本記事は、前記事「【CakePHP】DarkAuthComponentを使ってみる」の続編です。前記事をお読みでない方は、まずこちらをお読みください。
さて、前記事で「DarkAuthComponent」の実装方法などを書いてみたりしたのですが、当方の求めていた仕様の半分を満たしていませんでした。その仕様は「例えばゲストユーザのような、未ログインのユーザでもとりあえず使えるページや、VIPユーザのような特別なユーザのみがアクセスできるページが持てる」というものだったのですが、DarkAuthでは前半部分の、「ゲストユーザがアクセスできない」のです。
それに加え、DarkAuthはコントローラ単位で認証処理が出来ますが、アクション単位では出来ないというのも難点です。例えばusers/indexは認証済みでないと表示できないが、loginやjoinはゲストでもアクセスできる、といった具合の場合分けは是非ともしたいところです。
そこで、この2点を実現でき、しかも「簡単に」実装できる方法を考えてみました。
dark_auth.phpに注目してみますと、実際にアクセスの可否を調べている場所は「requiresAuth()」関数です。そこで、ここの初っぱなにチェックするルーチンを入れ、ゲストユーザだった場合の場合分けを行ってみます。
また、action毎のパーミッションについては、$_DarkAuth['required']['(action名)']のような指定方法にして(つまり配列を一段増やして)、さらにワイルドカード(もどき)の処理も入れることにします。つまり、アクション名に'*'を入れると、全てのアクションが対象になり、グループ名に'*'を入れると、全てのグループに対して処理を行う、といった動作になります。
dark_auth.phpは、次のように改造します(抜粋)。
app/controllers/components/super_dark_auth.php
class SuperDarkAuthComponent extends Object {
//(省略)
var $superuser_group = 'Root'; //これは既にある
var $undefined_group = 'NoGroup'; //←これを追加//(省略)
function requiresAuth($action_groups=array(),$deny_redirect=null){
$action = $this->controller->action;
if(!empty($action_groups)){
if(isset($action_groups[$action])){
$groups = $action_groups[$action];
}else
if(isset($action_groups['*'])){
$groups = $action_groups['*'];
}else{
$groups = array();
}
}else{
$groups = array();
}
if(array_search('*', $groups) !== false){ //2008-10-15修正
return true;
}
//↑↑↑修正はここまで↑↑↑
if(empty($this->current_user)){
if(array_search($this->undefined_group, $groups) !== false){
return true;
}else
// Still no info! render login page!
if($this->from_post){
$this->Session->setFlash($this->login_failed_message);
}
echo $this->controller->render($this->login_view);
exit();
}else{
if($this->from_post){
// user just authed, so redirect to avoid post data refresh.
$this->controller->redirect($this->here,null,null,true);
exit();
}
// User is authenticated, so we just need to check against the groups.
if( empty($groups) ){
// No Groups specified so we are good to go!
$deny = false;
}else{
$deny = !$this->isAllowed($groups);
}
if($deny){
// Current User Doesn't Have Access! DENY
if($deny_redirect){
$this->controller->redirect($deny_redirect);
exit();
}else{
echo $this->controller->render($this->deny_view);
exit();
}
}
}
return true;
}//(省略)
}
修正箇所はたったこれだけです。
同じコンポーネント名でも良いのですが、同じだと紛らわしいので、仮に「SuperDarkComponent」としましょう(笑)。
次に、コントローラ内の$_DarkAuth配列を修正します。
例えば次のように指定します。
app/controller/users_controller.php
var $_DarkAuth = array(
'required' => array(
'index' => array(
'Huga',
),
'edit' => array(
'Huga',
),
'join' => array(
'NoGroup',
),
'*' => array(
'*',
),
),
'onDeny' => '/',
);
上の例では、indexとeditはHugaグループのみ、joinはゲストのみ、それ以外は誰でもアクセスが出来ます。
ちなみに、コンポーネント名をDarkAuthからSuperDarkAuthに変更したので、users_controller.php内のコンポーネント名は全て変更してください。でないと動きません。その他の場所については今回触っていないため、全てDarkAuthの名称になっていると思います。
また、「NoGroup」の名称はbeforeFilter()内で変更することが出来ます。グループ名でこの名前を使いたい場合は変更します。逆に、NoGroupというグループはgroupsテーブル内に存在しないようにしてください。
上記改造後に実行してみると、おおよそそのように動くのが確認できるかと思います。
全ての機能については検証していないので分からないのですが、とりあえず必要条件は満たせそうです。当方のサイトも、これをベースに作っていきたいと思います。
I need to contact site admin urgently. Can you understand me?
Hope for no silence
What do you want to ask me?
Please write a summary to a new comment of the article.