今回は、ユーザー名とパスワードの代わりにユーザーを特定するキー(パスポートと呼びます)をクッキーとデータベースに記録します。ログインしていないユーザーがパスポートを持っていればデータベースからユーザーを特定し、自動でログインさせます。この例では、Authコンポーネントが使うセッションの有効期限とパスポートが使うクッキーの有効期限が異なります。


データベースにPassportsテーブルを作成します。

CREATE TABLE `passports` (
  `id` int(11) NOT NULL auto_increment,
  `user_id` int(11) NOT NULL default '0',
  `passport` varchar(60) NOT NULL default '',
  `updated` datetime NULL ,
  PRIMARY KEY  (`id`)
)


モデルを用意します。パスポートがユーザーに所属するようにアソシエーションを設定しておきます。

class Passport extends AppModel {
    var $name = 'Passport';
    var $belongsTo = array(
                                    'User' =>
				    array('className' => 'User',
						'foreignKey' => 'user_id',
				));
}


Usersコントローラを修正します。有効期限を$expiresで設定します。

class UsersController extends AppController {
    var $components = array('Auth','Cookie');
	var $name = 'Users';
	var $uses = array("Passport");//使用するモデルを追加
	var $expires = "2 weeks";//パスポートの有効期限
	
    function beforeFilter() {
        $this->Auth->autoRedirect = false;
    }
    
    function login() {
        $user=$this->Auth->user();//認証済みユーザを取得     
            if(!empty($this->data)){
                //フォームからのデータの場合               
                if (empty($this->data['User']['remember_me'])) {
                   //パスポート不要なので削除
                    $this->__passportDelete($user);
                } else {
                    //パスポート発行する
                    $this->__passportWrite($user);
                }
                unset($this->data['User']['remember_me']);
                if ($user ) {
                    //ログインできた、リダイレクトする
                    $this->flash("ログインしました。",$this->Auth->redirect());
                    exit;
                }
            }
            
        if ($user ) {
            //認証できたユーザー。
            $this->flash("ログインしています。",$this->Auth->redirect());                                 
        }else{
             //認証でなかったユーザー。
            $cookiePassport=$this->Cookie->Read('User');
            if($cookiePassport){
            //クッキーに記録したパスポートでログインしてみる
                $deadline = date('Y-m-d H:i:s', strtotime("-".$this->expires));
             //  比較演算子はキー側に(1.2betaからRCで仕様変更)
                $options=array('conditions'=>array('Passport.passport'=>$cookiePassport['passport'],'Passport.updated >'=>" $deadline"));
                $passport = $this->Passport->find("first",$options);
                if($passport){
                    //該当するパスポートが見つかった
                    $user['username']=$passport['User']['username'];
                    $user['password']=$passport['User']['password'];
                    if($this->Auth->login($user)){
                        //ログインできたので、クッキーを更新してリダイレクトする
                        $this->__passportWrite($passport);
                        $this->flash("自動ログインしました。",$this->Auth->redirect());
                    }
                }
            }
        }
        // ログイン用フォームを表示する   
    }

    
    function logout() {
        $user=$this->Auth->user();
        $this->__passportDelete($user);
        $this->Session->setFlash('ログアウトしました');
        $this->redirect($this->Auth->logout());//ログアウトし、ログイン画面へリダイレクト
    }
   
    function __passportDelete($user){
        $this->Cookie->del('User');
        $condition=array('Passport.user_id'=>$user['User']['id']);
        $this->Passport->deleteAll($condition);
    }
    
    function __passportWrite($user){
        $passport = array();            
        $passport['user_id']=$user['User']['id'];
        $passport['passport']=Security::generateAuthKey();識別用にユニークなキーを生成
        if(isset($user['Passport']['id']))$passport['id']=$user['Passport']['id'];
        $this->Passport->save($passport);
        
        $cookie = array('passport'=>$passport['passport']);
        $this->Cookie->write('User', $cookie, true,"+ ".$this->expires);   
    }
     
}

CakePHP Note (v1.3)

Index