読者です 読者をやめる 読者になる 読者になる

なか日記

一度きりの人生、楽しく生きよう。

CakePHPのAuthコンポーネントでパスワードを保存する際に暗号化する

CakePHPでAuthコンポーネントを使用すると簡単に認証機能を追加できますが、この時、パスワードは暗号化されたものとしてチェックが行われます。

SQLでみるとこんな感じ

SELECT `Administrator`.`id`,
    `Administrator`.`loginid`,
    `Administrator`.`password`,
    `Administrator`.`name`,
    `Administrator`.`created`,
    `Administrator`.`modified`,
FROM `hoge`.`administrators` AS `Administrator`
WHERE `Administrator`.`loginid` = 'admin'
AND   `Administrator`.`password` = 'b1b7c0fd30ed137e6597dbe4d2a8af972d7c44f5'
LIMIT 1

一方、スキャフォールディングで作成したメンテナンス画面は勝手に暗号化してくれません。 ドキュメントにもそう書いてありますね(たぶん)。

http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#hashing-passwords

結果、スキャフォールディングで作成した画面で登録したユーザでログインしようとしてもパスワードが一致せずにログインできないという状態になってしまいます。

で、ドキュメントの中に「モデルで暗号化して書き込みな」って示されているサンプルコードですが、編集時にパスワードを変更せずに更新するとパスワードのハッシュがどんどん書き換わって二度とログインできなくなってしまいます。

class User extends AppModel {
    public function beforeSave($options = array()) {
        if (isset($this->data['User']['password'])) {
            $this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
        }
        return true;
    }
}

そこで、以下の様な小細工をしました。

パスワードが変更されてなかったらそのまま書き込み、変更されていれば暗号化して書き込んでるだけですね。

class Administrator extends AppModel
{
    public function beforeSave($options = array())
    {
        $oldData = Administrator::find('first', array('conditions' => array('Administrator.id' => $this->data['Administrator']['id']),));

        $password = $this->data['Administrator']['password'];
        if ($oldData['Administrator']['password'] != $password) {
            $this->data['Administrator']['password'] = AuthComponent::password($password);
        }
        return true;
    }
}