端くれプログラマの備忘録 CakePHP [CakePHP] ユーザ登録とログイン認証を実装する (1)

[CakePHP] ユーザ登録とログイン認証を実装する (1)

良く出来たプラグインとかありそうだけど、自分の理解を深めるために手実装してみる。

CakePHPバージョンは2.7.3。

参考サイトは以下。

CakePHP 2.x – ユーザ登録(仮登録・メール・本登録)
http://kwski.net/cakephp-2-x/1100/

Creating a community in five minutes with CakePHP
http://www.aidanlister.com/2009/05/creating-a-community-in-five-minutes-with-cakephp/

ざっくり仕様

  • ユーザ用にユーザ登録画面を用意する
  • ユーザ登録画面には、ユーザ名、メールアドレス、パスワード(再入力あり)を入力する
  • ユーザ登録画面に入力されたメールアドレスに確認メールが送られる (仮登録)
  • 確認メールに記されているURLにアクセスすることでユーザ登録が完了する (本登録)
  • ユーザ登録完了後は、ユーザ名とパスワードでログインすることができるようになる
  • ログインするたびにDBに累積ログイン回数と最終ログイン日時を記録する
  • ユーザはログイン状態でパスワードが変更できる

usersテーブルの追加

ユーザ情報を格納するためのusersテーブルを追加する

CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(255) NOT NULL,
    `email` varchar(255) NOT NULL,
    `password` char(128) NOT NULL,
    `active` tinyint(4) NOT NULL DEFAULT '0',
    `logins` int(11) NOT NULL DEFAULT '0',
    `lastlogin` datetime DEFAULT NULL,
    `created` datetime NOT NULL,
    `modified` datetime NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `username` (`username`),
    UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • usernameとemailは重複禁止とする
  • passwordにはハッシュ化したパスワードを格納する
  • activeは登録状態を示す(0=仮登録、1=本登録) デフォルトは0
  • loginsは累積ログイン回数を記録する (ログインするごとにインクリメントされる)
  • lastloginには最終ログイン日時を記録する

Userモデルの作成

// app/Model/User.php

class User extends AppModel {
    
    public $validate = array(
        'username' => array(
            'length' => array(
                'rule' => array('minLength', 5),
                'message' => '5文字以上入力してください',
            ),
            'alphanum' => array(
                'rule' => 'alphanumeric',
                'message' => '英数字のみ入力してください',
            ),
            'unique' => array(
                'rule' => 'isUnique',
                'message' => '他のユーザに既に使われています',
            ),
        ),
        'email' => array(
            'email' => array(
                'rule' => 'email',
                'message' => '不適切なメールアドレスです',
            ),
            'unique' => array(
                'rule' => 'isUnique',
                'message' => '他のユーザに既に使われています',
            ),
        ),
        'password' => array(
            'empty' => array(
                'rule' => 'notBlank',
                'message' => '必ず入力してください',
            ),
        ),
        'password_confirm' => array(
            'compare' => array(
                'rule' => array('password_match', 'password'),
                'message' => 'パスワードが一致しません',
            ),
            'length' => array(
                'rule' => array('between', 6, 20),
                'message' => '6文字以上20文字以下のパスワードを入力してください',
            ),
            'empty' => array(
                'rule' => 'notBlank',
                'message' => '必ず入力してください',
            ),
        ),
    );

    //--------------------------------------------------------------------------
    // ヘルパー関数

    // パスワードと確認入力が一致するかチェックする
    public function password_match($field, $password) {
        return ($field['password_confirm'] === $this->data[$this->name][$password]);
    }

    // 本登録用のリンクに含めるハッシュを生成する
    public function getActivationHash() {
        if (!isset($this->id)) {
            return false;
        } else {
            return Security::hash($this->field('modified'), 'md5', true);
        }
    }

    //--------------------------------------------------------------------------
    // コールバック関数

    // データが保存される前に実行される
    public function beforeSave($options = array()) {
        // 平文パスワードをハッシュ化
        if (isset($this->data[$this->alias]['password'])) {
            $this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
        }
        return true;
    }
}

(次回へ続く)

全ソース (GitHub)
https://github.com/84kure/cakephp2-sample-auth