CakePHP2.xのユーザー認証(Auth)の実装とかなんとか – PHP

[PR]

これも今更ながら。毎度何かが抜けて慌てるのでポイントをメモ。

例によって、公式ドキュメントにちゃんと情報があることなので、そっち見たほうがいいとは思う!
http://book.cakephp.org/2.0/ja/core-libraries/components/authentication.html

AppControllerのcomponentsにAuthを追加。
あといい感じにカスタマイズ部分はパラメータ追加。

	var $components = array(
		'Session',
		'Cookie',
		'Auth' => array(
			'loginAction' => array('controller' => 'users', 'action' => 'login'),
			'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
			'logoutRedirect' => array('controller' => 'top', 'action' => 'index'),
			'authenticate' => array('Form' => array('userModel' => 'User', 'fields' => Array('username' => 'email')))
		)
	);

対象のModelのbeforeSaveでパスワードの暗号化

    public function beforeSave($options = array()) {
        // make a password for digest auth.
        $this->data['User']['digest_hash'] = DigestAuthenticate::password(
            $this->data['User']['username'], $this->data['User']['password'], env('SERVER_NAME')
        );
        return true;
    }

これやらないとパスワードが平文で保存されてしまい、ログインもできぬ。

Viewはログインとユーザー登録ページを追加。

signup.ctp

<div>
	<?php echo $this->Form->create('User', array('class' => 'form-horizontal'));?>
	<fieldset>
		<legend>ユーザー登録</legend>
		<?php
			echo $this->Form->input('email', array('label' => 'メールアドレス', 'required' => 'required'));
			echo $this->Form->input('password', array('label' => 'パスワード', 'required' => 'required'));
		?>
		<?php echo $this->Form->submit('登録');?>
    </fieldset>
    <?php echo $this->Form->end();?>
</div>

 login.ctp

<div>
    <?php echo $this->Form->create('User', array('class' => 'form-horizontal'));?>
    <fieldset>
        <legend>ログイン</legend>
        <?php
        echo $this->Form->input('email', array( 'label' => 'メールアドレス', 'required' => 'required'));
        echo $this->Form->input('password', array( 'label' => 'パスワード', 'required' => 'required'));
        echo $this->Form->submit('ログイン');
        ?>
    </fieldset>
    <?php echo $this->Form->end(); ?>
</div>

Users Controllerにこいつらとログアウト処理を追加。

	public function signup() {
		if ($this->request->is('post')) {
			// 必要があればデータ調整
			$this->request->data['User']['flg'] = 1;

			// 保存
			$this->User->create();
			if ($this->User->save($this->request->data)) {
				// そのままログイン処理してしまう。
				$id = $this->User->id;
				$this->request->data['User'] = array_merge($this->request->data['User'], array('id' => $id));
				$this->Auth->login($this->request->data['User']);

				// リダイレクト
				$this->Session->setFlash('ユーザー登録OK');
				$this->redirect(array('action' => 'index'));
			} else {
				$this->Session->setFlash('エラーや!');
			}
		}
	}

	public function login() {
		if ($this->request->is('post')) {
			if ($this->Auth->login()) {
				$this->Session->setFlash('ログインできたで!');
				$this->redirect($this->Auth->redirectUrl());
			} else {
				$this->Session->setFlash('エラーやで!');
			}
		}
	}

	public function logout() {
		$this->redirect($this->Auth->logout());
	}

あとは各Controllerで、認証不要のページは許してあげておく。

	public function beforeFilter() {
		$this->Auth->allow('*'); // このController全て認証不要
		// $this->Auth->allow('view', 'index'); // viewとindexは認証不要
		parent::beforeFilter();
	}

あと、個人的によくやるのはAppControllerのbeforeFilterで、ログイン状態の確認と共通ヘッダーとかで使うデータの取得。

	public $is_login = false;
	public $uid = 0;
	public $username = "ゲスト";

	public function beforeFilter() {
		$this->is_login = (bool)$this->Auth->user();
		if ($this->is_login) {
			$this->uid = $this->Auth->user('id');
			$this->username = $this->Auth->user('username');
		}
		$this->set('is_login', $this->is_login);
		$this->set('uid', $this->uid);
		$this->set('username', $this->username);
		parent::beforeFilter();
	}

こんなもんかな?他にあったらまた追記しよう。

 

追記)redirect()は2.3までだった。以降はredirectUrl()。

追記)loggedIn()も2.4までだった。以降はuser()を(bool)で型変換して判定。