端くれプログラマの備忘録 CakePHP [CakePHP] パスワードのリセット機能を実装する (1)

[CakePHP] パスワードのリセット機能を実装する (1)

先日実装したユーザ登録とログイン認証に、パスワード忘れ時のリセット機能を追加する。

CakePHPバージョンは2.7.3。

参考サイトは以下。

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

ざっくり処理手順

  • パスワード忘れ画面に登録メールアドレスを入力する
  • パスワードリセットのリンクがメールで送られる
  • リンクにアクセスするとパスワードがリセットされる
  • 新しいパスワードがメールで送られる

tokensテーブルの追加

パスワードリセットのリクエストを一意に識別するために、パスワードリセットのリンクにユニークなトークンを含めることにする。トークン及び紐付けされたユーザ情報を保存するためのtokensテーブルを追加する。

CREATE TABLE `tokens` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`token` varchar(32) DEFAULT NULL,
`data` text,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `token` (`token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Tokenモデルの作成

// app/Model/Token.php

class Token extends AppModel {
   
     // Create a new ticket by providing the data to be stored in the ticket.
    public function generate($data = null) {
        $data = array(
            'token' => substr(md5(uniqid(rand(), 1)), 0, 10),
            'data' => serialize($data),
        );
        if ($this->save($data)) {
            return $data['token'];
        }
        return false;
    }
   
    // Return the value stored or false if the ticket can not be found.
    public function get($token) {
        $this->garbage();
        $token = $this->find('first', array(
            'recursive' => -1,
            'conditions' => array('Token.token' => $token),
        ));
        if ($token) {
            $this->delete($token['Token']['id']);
            return unserialize($token['Token']['data']);
        }
        return false;
    }
   
    // Remote old tickets.
    public function garbage() {
        return $this->deleteAll(array('created < INTERVAL -1 DAY + NOW()'));
    }
}

(次回へ続く)