22
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

シンプルなユーザー登録

Last updated at Posted at 2015-05-06

CakePHP(2.6.4)を使ったシンプルなユーザー登録のメモ。

※本記事には修正が必要な個所がありました。(参考
※なお、上記修正内容はすでに反映済みです

#概要

ユーザー登録画面にて「メールアドレス」と「パスワード」を入力し登録を行う。
なお、ユーザー名は「メールアドレス」を利用する。

#実装内容

##Userモデル(User.php)及びUserテーブル

Userモデルには独自検証ルールと保存前処理を実装。
ユーザー登録時のパスワードのハッシュ化はbeforeSaveにてBlowfishPasswordHasherを用いて行う。

重複ユーザーの登録が行われないよう重複チェック(isUnique)を実装。
重複ユーザーの登録が行われないよう標準ルールのisUniqueを利用。
また、パスワード欄とパスワード(確認)欄の一致を検証するため一致チェック(passwordConfirm)を実装。
パスワードに利用可能な文字を半角英数字(記号可)とする為のチェック(alphanumericsymbols)を実装。

検証ルールについては主に以下の内容を指定。

メールアドレスをキーとして重複登録のチェックを標準ルールの重複チェック(isUnique)を指定。
パスワード欄には半角英数字(記号可)のみ入力可能とする為、Userモデルに実装した文字種チェック(alphanumericsymbols)を指定。
同様にパスワード欄とパスワード(確認)欄を用いてパスワードの誤入力(勘違い)を防ぐ為、両フィールドの一致をチェックする為、一致チェック(passwordConfirm)を指定。

User.php
<?php

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

class User extends AppModel {

    var $name = 'User';
    var $useTable = 'users';

	public $validate = array(
		'email' => array(
			array(
				'rule' => 'notEmpty', 
				'message' => 'メールアドレスを入力してください'
			), 
			array(
				'rule' => 'email', 
				'message' => '正しいメールアドレスを入力してください'
			), 
			array(
				'rule' => 'isUnique', 
				'message' => '入力されたメールアドレスは既に登録されています'
			), 
		),
		'password' => array(
			array(
				'rule' => 'notEmpty', 
				'message' => 'パスワードを入力してください'
			), 
			array(
				'rule' => 'alphanumericsymbols', 
				'message' => 'パスワードに使用できない文字が入力されています'
			), 
			array(
				'rule' => array('minLength', 8), 
				'message' => 'パスワードは8文字以上入力してください', 
			),
			array(
				'rule' => 'passwordConfirm', 
				'message' => 'パスワードが一致していません'
			), 
		),
		'password_confirm' => array(
			array(
				'rule' => 'notEmpty', 
				'message' => 'パスワード(確認)を入力してください'
			), 
		),
	);

	public function beforeSave($options = array()) {

		if (isset($this->data[$this->alias]['password'])) {
			$passwordHasher = new BlowfishPasswordHasher();
			$this->data[$this->alias]['password'] = $passwordHasher->hash(
				$this->data[$this->alias]['password']
			);
		}

    	return true;

	}

	public function passwordConfirm($check){

		//2つのパスワードフィールドが一致する事を確認する
		if($this->data['User']['password'] === $this->data['User']['password_confirm']){
			return true;
		}else{
			return false;
		}

	}

	public function alphanumericsymbols($check){
		$value = array_values($check);
		$value = $value[0];
    	return preg_match('/^[a-zA-Z0-9\s\x21-\x2f\x3a-\x40\x5b-\x60\x7b-\x7e]+$/', $value);
	}

}
user.sql
CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255),
    password VARCHAR(255),
    created DATETIME DEFAULT NULL,
    modified DATETIME DEFAULT NULL
) ENGINE = InnoDB;

##Signupコントローラー(SignupController.php)

Signupコントローラーではユーザー登録作業を実施。

indexアクションでは、入力データが送信されていない場合は「$this->render()」にてindexビュー(Signup/index.tpl)を表示し、入力データが存在する場合は「$this->User->invalidFields()」にて検査を実施。

検査を通った場合は入力内容を保存し、最後にサンクス画面を表示して終了。

なおセキュリティを高める為、Securityコンポーネントを利用。
不正なアクセスが行われた場合あらかじめ設定したblackholeメソッドの処理を実行。
(ここではエラーメッセージをセットし呼び出し元にリダイレクト)

SignupController.php
<?php

class SignupController extends AppController {

	public $name = 'Signup';
	public $uses = array('User');
	public $components = array(
		'Security', 
	);

    public function beforeFilter() {
        parent::beforeFilter();
		$this->Security->blackHoleCallback = 'blackhole';
    }

	public function index(){

		if(!$this->request->data){
			$this->render();
			return;
		}

		//入力データをセット
		$this->User->set($this->request->data);

		//入力内容を検査
		if($this->User->validates()){

			//モデルの状態をリセット
			$this->User->create();

			//入力済みデータをモデルにセット
			$user = array('User' => $this->request->data['User']);

			//データを保存
			$this->User->save($user);

			//サンクス画面を表示
			$this->render('thanks');

		}

	}

	public function blackhole($type) {

		$this->Session->setFlash('不正なリクエストが行われました');
		$this->redirect(array('controller' => $this->controller, 'action' => $this->action));

	}

}

##Usersコントローラー(UsersController.php)

Usersコントローラーでは、ログイン及びログアウト処理と認証を必要なページとしてmypageアクションを実装。

今回はユーザー名としてメールアドレスを利用する為、「fields」にて「'username' => 'email'」を指定する。
またハッシュ化にBlowfishPasswordHasherも利用している為、「passwordHasher」にて「Blowfish」を指定。

なお、loginアクション及びlogoutアクションは未認証状態でもアクセス可能とする必要がある為、あらかじめ「beforeFilter」にて除外を行う。

loginアクションにて認証情報が送信されてきた場合は、ログイン処理を実施する。
認証が通った場合は、あらかじめ設定されたURLにリダイレクトする。

logaoutアクションが呼ばれた場合、ログアウト処理を実施しログアウト完了画面を表示する。

こちらでもセキュリティを高める為、Securityコンポーネントを利用。
不正なアクセスが行われた場合あらかじめ設定したblackholeメソッドの処理を実行。
(ここではエラーメッセージをセットし呼び出し元にリダイレクト)

UsersController.php
<?php

class UsersController extends AppController {

	public $name = 'Users';
	public $uses = array('User');
	public $components = array(
		'Auth' => array(
			'authenticate' => array(
				'Form' => array(
					'passwordHasher' => 'Blowfish', 
					'fields' => array(
						'username' => 'email', 
						'password' => 'password', 
					), 
				)
			), 
			'loginAction' => '/users/login', 
			'loginRedirect' => '/users/mypage', 
		), 
		'Session', 
		'Security', 
	);

    public function beforeFilter() {
        parent::beforeFilter();
        $this->Auth->allow('login', 'logout');
		$this->Security->blackHoleCallback = 'blackhole';
    }

	public function login() {

		//フォームから情報が送信された場合のみの認証を実施
		if ($this->request->is('post')) {

			//認証処理を実施
			if($this->Auth->login()){
				//認証に成功した場合は、設定されたURLへリダイレクト
				return $this->redirect($this->Auth->redirectUrl());
			}else{
				$this->Session->setFlash('ログインに失敗しました');
			}

		}

	}

	public function logout() {

		//ログアウトを実施
		$this->Auth->logout();

		//ログアウト完了画面を表示
		$this->render('logout');

	}

    public function mypage() {

	}

	public function blackhole($type) {

		$this->Session->setFlash('不正なリクエストが行われました');
		$this->redirect(array('controller' => $this->controller, 'action' => $this->action));

	}

}

#総括及び課題(疑問)

最もシンプルなユーザー登録の処理の為、アカウントの有効化やメールアドレスの検証等の処理は未実装。

パスワードのハッシュ化はSimplePasswordHasherにて行ったが、アルゴリズムの選択や強度の設定ができるはずなので確認が必要。
パスワードのハッシュ化はBlowfishPasswordHasherにて行ったが、強度の設定等についても確認が必要。

その他、例えばソーシャルログインも実装する場合も考慮するとテーブル構成は見直す必要があると思われる。
(メールアドレスが必ず入手可能ではない為)

#参考

ホワイトスペースと半角記号にマッチする正規表現

#【参考】各種ビュー

Signup/index.ctp
<?php echo $this->Form->create(); ?>

<?php echo $this->Form->label('User.email', 'メールアドレス:'); ?>
<?php echo $this->Form->text('User.email'); ?>
<?php echo $this->Form->error('User.email'); ?>

<?php echo $this->Form->label('User.password', 'パスワード:'); ?>
<?php echo $this->Form->password('User.password'); ?>
<?php echo $this->Form->error('User.password'); ?>

<?php echo $this->Form->label('User.password_confirm', 'パスワード(確認):'); ?>
<?php echo $this->Form->password('User.password_confirm'); ?>
<?php echo $this->Form->error('User.password_confirm'); ?>

<?php echo $this->Form->end('登録'); ?>
Signup/thanks.ctp
登録しました
Users/login.ctp
<?php echo $this->Form->create(); ?>
<?php echo $this->Form->label('User.email'); ?>
<?php echo $this->Form->text('User.email'); ?>
<?php echo $this->Form->label('User.password'); ?>
<?php echo $this->Form->password('User.password'); ?>
<?php echo $this->Form->end('ログイン'); ?>
Users/logout.ctp
<p>ログアウトしました</p>
<p><a href="/users/login/">ログイン</a></p>
Users/mypage.ctp
<p>マイページ</p>
<p><a href="/users/logout/">ログアウト</a></p>
22
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?