AuthCompornent 決着

わからなくてもういやだ><だったAuthCompornent。
正直、タイプミスとかで動かないのかと思ってたけど、認識がそもそも…。な事が原因だった。

前回のブログだと何がしたいのか、わかりづらいので、まとめる。
やりたかった事

  • ユーザをつくる。ユーザは、グループA、グループBのどちらかに属す。(Aモデル、Bモデル)。
  • ユーザを作成したあとに、ログインすると自分が属しているページに遷移したい。
  • A組の人はA/index,B組の人はB/indexに遷移したい。
  • →そのためには、AuthCompornentを利用し、ログイン後にリダイレクト先を操作したい。
    やったこと

  • 標準的なusersテーブルを作成。
  • Aモデル、Bモデルは実装しないで$scaffoldで組み立てる。
  • usersテーブルには、mail,password,kindなぞを持たせる。認証はmail,passwordで。
  • AuthCompornentの認証としてはmail,passwordをつかう。
  • 基本的な設定はapp/app_controller.phpのbeforeFilter();で記述する。
  • users_contoroller.phpでparent::beforeFilter();を呼ぶ。
  • できなかったこと

  • ログイン後、認証データからユーザ情報のkindを判断し、A組かB組かでリダイレクト先を制御。
  • 認証自体の動きはできていたが、認証後、ユーザーの情報を取得することができなかった。
    ここでつまづいた。
    さて昨日のソースコードですが、わかりづらかったのでコメントでこのようにしてみました。

    class UsersController extends AppController {
    
    //start ここから重要な箇所
    	  var $name = 'Users';
    	  var $helpers = array('Html', 'Form');
    	 
    	  function beforeFilter() {
    	    parent::beforeFilter();
    	    $this->Auth->allow('add');
    	    $user = $this->Auth->user();//AuthComponent;
            //問題の箇所。ここで振り分ける処理をかいたが、動かない。
     	if($user['User']['kind']=='1'){
       		$this->redirect('/companies/index');
       	}elseif($user['User']['kind']=='2'){
       		$this->redirect('/members/index');
       	}  
    
       //ここでかいても、nullだの言われる。
       var_dump($user);
    	   }
    	 
    	  function login(){
    	  }
    //ここまでが重要なコード。以下はどうでも良い。
    	  function logout(){
    	    $this->Session->setFlash('ログアウトしました');
    	    $this->Auth->logout();
    	    $this->redirect(array('action' => 'login'));
    	  }
    	 
    	  function add() {
    	    if (!empty($this->data)) {
    	        $this->User->create();
    	        $this->User->save($this->data['User']);
    	        //登録ユーザーでその後の登録ページを遷移する
    	        if($this->data['User']['kind']==0){
    	            $this->redirect('/companies/add');
    	        }elseif($this->data['User']['kind']==1){
    	            $this->redirect('/members/add');
    	        }
    	    }
    	  }
    }
    

    ここで、読者の方は「…そこで書いてもだめでしょ…」とすでにお気づきなんだとは思うのですが、許して><
    ここ、だいぶ躓きました。beforeFilterの中でリダイレクト先を指定するコードをかくためにそこで認証データを参照するのですが、
    参照しても参照しても、現在ログインしているユーザの情報が取得できない。
    ・セッションをクリアする
    ・Aさんでログインする(kind==1の人)
    ・リダイレクトは本来ならcompanies/indexに飛んでほしいけど飛ばない(上記のソースでいえばifにもelseifにもはいらない)。
    ・ログイン画面に戻って、Bさん(kind==0の人)でログインする
    ・ログインするとAさん(Bさんじゃないのかよ)が飛ぶべきログイン先(companies/index)にリダイレクトする

    というように、「1世代古い状態」でなぜかリダイレクトを参照するという状況になり、大変なことに。(メンタル)

    ここで「…なにこれ」と思って月曜から悩んで今日に至ったわけですが、賢明な読者の方はお気づきでしょうが、
    beforeFilter()内ではまだ認証は行われていないのでとりようがないということに気がつくのに2日かかったという…。
    きがついた原因としてはねねとまつの小部屋でのコードでした。
    多分このソースをまるごとコピーして作成していたらまた違ったとおもうのですが、リダイレクトの処理については見落としていました。
    標準的なブログはログイン後のリダイレクトについてどこにかくべきかなんて名言してないですよね。いやログインした後のログイン先を認証データで判断するということ自体があまり必要のないことなのではないかと思います。ログイン認証時のデータを参照する必要がなければbeforeFilter()に設定するので問題ないのですから。

    app_contorollerにかこうが、users_controllerにかこうが、ログイン認証を行った後の認証データを参照したい場合はbeforeFilterではなく、app_controllerのlogin()内にかかなくてはいけないのです。…はい。一世代ログイン情報が古かったのはbeforeFilterで参照していたものは、「すでにログインしたとみなされたふるい認証データ」だったということになります。つ、ま、り。

    <?php
    class UsersController extends AppController {
      var $name = 'Users';
      var $helpers = array('Html', 'Form');
      
      function beforeFilter() {
    //ここではまだ認証を通っていない。ここで参照しようとすると残って(いれば)過去の認証データが参照できる。意味なし。
      	parent::beforeFilter();
        $this->Auth->allow('add');
      }
    
    
      function login(){
    //ここで初めて最新のログイン認証を通ったユーザーの情報が取得できる。
    	$user = $this->Auth->user();
      	if($user['User']['kind']=='1'){
       		$this->redirect('/companies/index');
       	}elseif($user['User']['kind']=='0'){
       		$this->redirect('/members/index');
       	}  
      }
      
      function logout(){
        $this->Session->setFlash('ログアウトしました');
        $this->Auth->logout();
        $this->redirect(array('action' => 'login'));
      }
    
      function add() {
        if (!empty($this->data)) {
            $this->User->create();
            $this->User->save($this->data['User']);
            //登録ユーザーでその後の登録ページを遷移する
            if($this->data['User']['kind']==0){
            	$this->redirect('/companies/add');
            }elseif($this->data['User']['kind']==1){
            	$this->redirect('/members/add');
            }
        }
      }
    }
    
    

    てな具合に。一応app/の上位のAppController も乗せておく。

    <?php
    class AppController extends Controller {
    	//var $components = array('Auth');
    	var $components = array('Auth','DebugKit.Toolbar');
    	var $user;
    	
    	
    	function beforeFilter(){
    		//リダイレクトを指定したいのでfalseに指定する
    		$this->Auth->autoRedirect=false;
    		$this->Auth->fields = array('username' => 'mail','password' => 'password');
    		$this->set('user',$this->Auth->user());
    		$this->Auth->loginError = 'ログインエラー';
    		$this->Auth->authError = 'ログインしていません';
    	}
    }
    ?>
    

    このようにすることで、ログイン認証を行ったあとのユーザ情報を正確に取得することができました。
    AuthCompornentの動きで、ユーザがログインした場合Autn->login()が呼び出されるタイミングが自分の中でわかっていなかったのが原因ですね。・・・。users_contorollerにはlogin()はあったのですが、中身はなかった。器だけ用意しとけばいいだろと思っていたので、明確に根拠はなかったのですが、AppControllerのbeforeFilterで呼び出されるようなきがしていました。今も実は根拠はない。実際に動かしてみたらlogin()では参照できたのでそこで初めて参照できる、という事実を知っただけですが・・。
    あたりまえですが、beforeFilterというのはbeforeFilterなんだよね…。AuthCompornentが実際にログイン処理を行っているタイミングがいまいち把握できていないことが理由で、下らんことに時間をかけてしまった…。。。。。

    もし、この記事で同じようなことに遭遇した人がいたら、そうよね!そうよね!と分かち合いたい。そんな人いないか…。
    タイプミスで動きませんでした;;のほうが格好よかったかもしれない。今後、開発で難儀しそうだなあ…、、、とほほ。
    週末、もうちょっと遷移を進めてみることにしよう。

    広告

    2 Replies to “AuthCompornent 決着”

    1. Authのメイン処理はstartup()コールバック内なので、もし直後に処理を行いたい別途コンポーネントを作成してやる必要がありそうです。その場合、Authより後にそのコンポーネントを記述しておけば、Auth処理の後にできます。失敗されたkind処理はここに書いたらできるかも??

    2. コメントありがとうございます。

      新しくコンポーネントを作成するという手があるのですね。
      現状、login()の中に記述することでやりたいことを実現できているのですが、
      今度は現状の機能にAdmin routingを併用したいと考えているのです。
      そうなるとますます複雑になるので、別枠に設けるという手のほうがよいのかもしれません。
      ブログのようなCMSの場合、管理者もユーザも共にログインを行い、認証はAuthにさせ、いわゆるkind=99のようなユーザを管理者として制御させる…という機能にしてみようと考えています。新しいコンポーネントを作成するっていうのはちょっと敷居が高いきがしますが、他のコンポーネントを見ながらそちらも視野にいれてみようと思います。

    コメントを残す

    以下に詳細を記入するか、アイコンをクリックしてログインしてください。

    WordPress.com ロゴ

    WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

    Twitter 画像

    Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

    Facebook の写真

    Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

    Google+ フォト

    Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

    %s と連携中