CakePHP 1.2 の AuthComponent はとても便利なのですが、POSTされたパスワードの値を自動的に暗号化(hash)してしまうため、ユーザの create/update を行う際のバリデーションが困難になります。そこで AuthComponent を補助する AuthModel ビヘイビアを作ってみました。
auth_model.php – gist:188066
このビヘイビアを使うことで
- 標準のバリデーション機能を使ってパスワード入力値を検証できるようになります
- 「再入力」による確認を行うための sameValue バリデータが使えるようになります
- データ更新時に「パスワード欄が空ならパスワードを変更しない」という動作を簡単に実現できます
以下、password カラムを備えた users テーブル(すなわち User モデル)を例に使い方を説明していきます。
まず User モデルに AuthModel ビヘイビアを登録してください。いくつか使用可能なオプションがありますが最後に説明します。
class User extends AppModel {
var $actsAs = array('AuthModel');
}
次にユーザ登録用のビューを作ります。AuthComponent による自動変換処理を回避するため、パスワード入力用のフィールドには本来のカラム名とは異なる名前を使用してください。AuthModel ビヘイビアはデフォルトで password_input という名前を使用するので、特にこだわりがなければこの名前を使うことをおすすめします。またパスワード再入力確認用のフィールドも用意しておきます。こちらは名前は何でも構いません。下の例では password_confirmation にしています。
<?php
echo $form->create('User');
echo $form->input('username', array('label' => 'ユーザ名'));
echo $form->input('password_input',
array('type' => 'password',
'label' => 'パスワード',
'value' => ""));
echo $form->input('password_confirmation',
array('type' => 'password',
'label' => 'パスワード(再入力)',
'value' => ""));
echo $form->end('作成');
?>
更新用のビューもほぼ同じ構成です。パスワードを空にした場合は変更されない、という説明書きを加えておきます。
<?php
echo $form->create('User');
echo $form->hidden('id');
echo $form->input('username', array('label' => 'ユーザ名'));
echo $form->input('password_input',
array('type' => 'password',
'label' => 'パスワード',
'value' => ""));
echo $form->input('password_confirmation',
array('type' => 'password',
'label' => 'パスワード(再入力)',
'value' => ""));
echo $form->end('更新');
?>
※パスワードを空欄にした場合は更新されません
そしてこの password_input フィールドに対するバリデーションを User モデルに設定していきます。以下の例では3つの設定を行っています。
- 入力は必須(requiredルール)
- 文字数は6文字以上(lengthルール)
- 「再入力」フィールドと値が一致(confirmルール)
最後のルールは AuthModel ビヘイビアが提供する sameValue バリデータを使います。このバリデータに対する唯一のオプションは再入力用フィールドの名前です。
class User extends AppModel {
var $actsAs = array('AuthModel');
var $validate = array('password_input' =>
array('required' =>
array('rule' => '/.+/',
'required' => true,
'allowEmpty' => false,
'last' => true,
'on' => 'create',
'message' => 'パスワードを入力してください'),
'length' =>
array('rule' => array('minLength', 6),
'allowEmpty' => true,
'last' => true,
'message' => 'パスワードは6文字以上で入力してください'),
'confirm' =>
array('rule' => array('sameValue', 'password_confirmation'),
'allowEmpty' => true,
'message' => 'パスワードと再入力の値が一致しません')));
}
それぞれのルールにおける required, allowEmpty, on, last オプションの設定が少し複雑ですが、よく分からなければCookbookを参照してください。
最後に UsersController です。beforeFilter 中で setAuthComponent メソッドを呼び出し、AuthComponent を登録しておきます(実は AuthComponent の中でデフォルトのhashアルゴリズムを使用している限り、この操作は必要ありません。しかし将来的に互換性の問題が発生する可能性もあるので、Userモデルのcreate/updateを行うコントローラでは必ず実行しておいてください)。
ユーザの追加/更新を行うadd/editアクションの中では特別な操作は必要ありません。
class UsersController extends AppController {
function beforeFilter() {
parent::beforeFilter();
$this->User->setAuthComponent($this->Auth);
}
function add() {
if (!empty($this->data)) {
if ($this->User->save($this->data)) {
$this->Session->setFlash('ユーザを作成しました。');
$this->redirect('index');
} else {
$this->Session->setFlash('エラーを修正してください。');
}
}
}
function edit($id = null) {
if(empty($this->data)) {
if (!$id || !($row = $this->User->findById($id))) {
$this->redirect('index');
}
$this->data = $row;
} else {
if($this->User->save($this->data)) {
$this->Session->setFlash('ユーザ情報を更新しました。');
$this->redirect('index');
} else {
$this->Session->setFlash('エラーを修正してください。');
}
}
}
}
注意
このビヘイビアを使用すると直接パスワード用カラムに値を設定して保存することができなくなります(セキュリティ上の配慮)。この制約を回避するには save メソッドの validate オプションを無効にして実行してください。
//ユーザ名 = パスワード = admin のユーザを追加
function install() {
$initialUser = array('User' =>
array('username' => 'admin',
'password' => $this->Auth->password('admin')));
$validate = false;
if($this->User->find('count') == 0) {
$this->User->save($initialUser, $validate);
}
$this->redirect('/');
}
応用
データ更新時の「パスワード入力欄が空ならパスワードを変更しない」動作が不要な場合、required ルールの on => create オプションを取り除いてください。さらに、滅多にないことだとは思いますが、空のパスワードを許可する場合は下記の allow_blank オプションを有効にしてください。
オプション
| キー |
型 |
デフォルト値 |
説明 |
| column |
string |
password |
パスワードを保存するカラムの名前 |
| input |
string |
password_input |
パスワード入力用のフィールド名 |
| allow_blank |
bool |
false |
空のパスワード使用可否 |
| hash_function |
callback |
array(Security,hash) |
パスワードのハッシュを求める際に使用するコールバック |
全てのオプションを設定した場合の例:
class User extends AppModel {
var $actsAs = array('AuthModel' =>
array('column' => 'secret',
'input' => 'secret_input',
'allow_blank' => true,
'hash_function' => 'md5'));
}
参考にしたサイト