カテゴリー : Auth

CakePHPでログアウト処理を呼び出したい

CakePHPでAuthコンポーネントを利用してログイン管理をしていて

退会処理を行った場合の実装で、コントローラーから

ログイン処理を呼び出したいということがあったのでメモ。

想像通り、簡単でした。

$this->Auth->logout();

を実行するだけでした。

退会しても、ユーザー情報は物理削除したくないので

usersテーブルに削除フラグを設定しておき、

「退会」のタイミングでこれを「2」に更新します。

退会用のページを作成し、退会理由を尋ねるための質問を用意します。

質問に回答してもらい、退会処理を実行します。

その退会処理の実装です。

$this->request->data['Entrepreneur']['delete_flg'] = '2';
if ($this->Entrepreneur->save($this->request->data, array('validate'=>false))) {
  $this->Auth->logout();
  return $this->redirect(array('action' => 'cancel_comp'));
} else {
  $this->Session->setFlash(__('退会処理に失敗しました。再度お試しください。'));
}

削除フラグを「2」に更新した後、ログアウト処理を実行し

退会完了画面に飛ばします。

ログアウトした状態になるので、

cancel_compはログインしていなくてもアクセスできるようにしておきます。

function beforeFilter() {
  parent::beforeFilter();
  $this->Auth->allow('cancel_comp');
}

CakePHPでログイン認証

CakePHPでログイン認証を実装します。
パスワードを暗号化して保存しますので、ユーザー編集画面でパスワードをデフォルトで空欄にし、入力した場合のみ変更する実装にします。

まずはユーザーテーブルを作成。

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` text,
  `username` text,
  `password` text,
  `deleted` smallint(6) DEFAULT '0',
  `created` datetime DEFAULT NULL,
  `updated` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ;

Userモデルを作成します。
app/Model/User.php
bakeで作成したものに、以下の内容を追加しました。

■パスワードの暗号化

App::uses('SimplePasswordHasher', 'Controller/Component/Auth');

AuthコンポーネントのSimplePasswordHasherを使用します。

    public function beforeSave($options = array()) {
        if (!$this->id) {
            $passwordHasher = new SimplePasswordHasher();
            $this->data['User']['password'] = $passwordHasher->hash($this->data['User']['password']);
        } else if ($this->id && $this->data['User']['password1']) {
            $passwordHasher = new SimplePasswordHasher();
            $this->data['User']['password'] = $passwordHasher->hash($this->data['User']['password1']);
		}
        return true;
    }

beforeSaveで、保存前にpasswordを暗号化します。
編集画面で、パスワード欄に何も入力しない場合は変更したくないので、変更画面(views/users/edit)のパスワードをpassword1として、これが入力されている場合に暗号化してpasswordにセットします。
登録画面では、暗号化して保存します。

■バリデーション
$validateで設定します。
パスワードは、登録画面のみ必須にしたいので、「’on’ => ‘create’」を指定します。
また、usernameは半角英数のみのユニークにしたいので、alphaNumericとisUniqueを指定します。
alphaNumericは日本語を通してしまうので、正規表現を使ってエラーチェックを設定します。

<?php
App::uses('AppModel', 'Model');
App::uses('SimplePasswordHasher', 'Controller/Component/Auth');

/**
 * User Model
 *
 */
class User extends AppModel {

    public function beforeSave($options = array()) {
        if (!$this->id) {
            $passwordHasher = new SimplePasswordHasher();
            $this->data['User']['password'] = $passwordHasher->hash($this->data['User']['password']);
        } else if ($this->id && $this->data['User']['password1']) {
            $passwordHasher = new SimplePasswordHasher();
            $this->data['User']['password'] = $passwordHasher->hash($this->data['User']['password1']);
		}
        return true;
    }

/**
 * Display field
 *
 * @var string
 */
	public $displayField = 'name';

/**
 * Validation rules
 *
 * @var array
 */
	public $validate = array(
		'name' => array(
			'notEmpty' => array(
				'rule' => array('notEmpty'),
				'message' => '必須入力です',
				//'allowEmpty' => false,
				//'required' => false,
				//'last' => false, // Stop validation after this rule
				//'on' => 'create', // Limit validation to 'create' or 'update' operations
			),
		),
		'username' => array(
			'notEmpty' => array(
				'rule' => array('notEmpty'),
				'message' => '必須入力です',
				//'allowEmpty' => false,
				//'required' => false,
				//'last' => false, // Stop validation after this rule
				//'on' => 'create', // Limit validation to 'create' or 'update' operations
			),
			'alphaNumeric' => array(
				'rule' => array('alphaNumeric'),
				'message' => '半角英数字のみ入力してください',
				//'allowEmpty' => false,
				//'required' => false,
				//'last' => false, // Stop validation after this rule
				//'on' => 'create', // Limit validation to 'create' or 'update' operations
			),
			'isUnique' => array(
				'rule' => array('isUnique'),
				'message' => 'このログインIDは既に登録されています'
			),
		),
		'password' => array(
			'notEmpty' => array(
				'rule' => array('notEmpty'),
				'message' => '必須入力です',
				//'allowEmpty' => false,
				'required' => true,
				'last' => true, // Stop validation after this rule
				'on' => 'create', // Limit validation to 'create' or 'update' operations
			),
		),
	);

	public function alphaNumeric($check) {
	    $value = array_values($check);  // 配列の添字を数値添字に変換して・・・
	    $value = $value[0];     // 最初の値を取る
	    return preg_match('/^[a-zA-Z0-9]+$/', $value);
	}
}

次にコントローラーを作成します。
app/Controller/UsersController.php

<?php
App::uses('AppController', 'Controller');
/**
 * Users Controller
 *
 * @property User $User
 * @property PaginatorComponent $Paginator
 */
class UsersController extends AppController {

/**
 * Components
 *
 * @var array
 */
	public $components = array('Paginator');

	function beforeFilter() {
		parent::beforeFilter();

		$this->Auth->allow('add', 'edit', 'logout');
	}

	function login() {
		$this->layout = 'simple';
		if ($this->request->is('post')) {
			if ($this->Auth->login()) {
				$this->redirect($this->Auth->redirect());
			} else {
				$this->Session->setFlash(__('Invalid username or password, try again'));
			}
		}
	}

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

/**
 * index method
 *
 * @return void
 */
	public function index() {
		$this->User->recursive = 0;
		$this->set('users', $this->Paginator->paginate());
	}

/**
 * view method
 *
 * @throws NotFoundException
 * @param string $id
 * @return void
 */
	public function view($id = null) {
		if (!$this->User->exists($id)) {
			throw new NotFoundException(__('Invalid user'));
		}
		$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
		$this->set('user', $this->User->find('first', $options));
	}

/**
 * add method
 *
 * @return void
 */
	public function add() {
		if ($this->request->is('post')) {
				$this->User->create();
				if ($this->User->save($this->request->data)) {
					$this->Session->setFlash(__('The user has been saved.'));
					return $this->redirect(array('action' => 'add_comp'));
				} else {
					$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
				}
		}
	}
	function add_comp(){
	}

/**
 * edit method
 *
 * @throws NotFoundException
 * @param string $id
 * @return void
 */
	public function edit($id = null) {
		if (!$id && empty($this->request->data)) {
			throw new NotFoundException(__('Invalid user'));
		}
		if ($this->request->is(array('post', 'put'))) {
				if ($this->User->save($this->request->data)) {
					$this->Session->setFlash(__('The user has been saved.'));
					return $this->redirect(array('action' => 'edit_comp'));
				} else {
					$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
				}
		} else {
			$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
			$this->request->data = $this->User->find('first', $options);
			$this->request->data['User']['password'] = null;
		}
	}
	function edit_comp(){
	}


/**
 * delete method
 *
 * @throws NotFoundException
 * @param string $id
 * @return void
 */
	public function delete($id = null) {
		$this->User->id = $id;
		if (!$this->User->exists()) {
			throw new NotFoundException(__('Invalid user'));
		}
		$this->request->onlyAllow('post', 'delete');
		if ($this->User->delete()) {
			$this->Session->setFlash(__('The user has been deleted.'));
		} else {
			$this->Session->setFlash(__('The user could not be deleted. Please, try again.'));
		}
		return $this->redirect(array('action' => 'index'));
	}
}

次に、AppController.phpで、Authコンポーネントの設定を行います。
app/Controller/AppController.php

<?php
/**
 * Application level Controller
 *
 * This file is application-wide controller file. You can put all
 * application-wide controller-related methods here.
 *
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @package       app.Controller
 * @since         CakePHP(tm) v 0.2.9
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */

App::uses('Controller', 'Controller');

/**
 * Application Controller
 *
 * Add your application-wide methods in the class below, your controllers
 * will inherit them.
 *
 * @package		app.Controller
 * @link		http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
 */
class AppController extends Controller {
    var $components = array('Session', 
            'Auth' => array(
                'authenticate' => array('Form' => array('scope' => array('User.deleted' => '0'),
														))
            ),
			);
}

最後にviewを作成します。
app/View/Users/add.ctp

<!-- app/View/Users/add.ctp -->
<div class="users form">
<?php echo $this->Form->create('User'); ?>
    <fieldset>
        <legend><?php echo __('Add User'); ?></legend>
        <?php echo $this->Form->input('username');
        echo $this->Form->input('password');
    ?>
    </fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>

ユーザー情報の編集画面です。
パスワードを「password1」にします。
app/View/Users/edit.ctp

<!-- app/View/Users/edit.ctp -->
<div class="users form">
<?php echo $this->Form->create('User', array('action'=>'edit')); ?>
    <fieldset>
        <legend><?php echo __('Add User'); ?></legend>
        <?php echo $this->Form->input('username');
        echo $this->Form->input('password1');
    ?>
    </fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>

ログイン画面です。
app/View/Users/login.ctp

<!-- app/View/Users/login.ctp -->
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('User'); ?>
    <fieldset>
        <legend><?php echo __('Please enter your username and password'); ?></legend>
        <?php echo $this->Form->input('username');
        echo $this->Form->input('password');
    ?>
    </fieldset>
<?php echo $this->Form->end(__('Login')); ?>
</div>