CakePHPのAuthコンポーネントは簡単に認証ステムを作れるので便利なのですが、誰でもユーザ登録できるようにしようと思うと若干工夫が必要でした。
誰でもユーザ登録できるようにする為には、
1. ユーザ名の重複はNG、設定できるパスワードにもルールを決める
→モデルのバリデーションで設定する
2. パスワード入力欄は普通のテキストフィールドにする
→ユーザが自分で設定するパスワードを視認できるようにする為
3. addアクション(ユーザ追加)は認証からはずす
まずはさらっと書いてみます。
> モデル(user.php)
<?php
class User extends AppModel {
var $name = 'User';
var $validate = array(
'username' => array(
'notempty' => array(
'rule' => array('notempty'), // 未入力チェック
),
'isUnique' => array(
'rule' => 'isUnique', // 重複チェック
),
),
'password' => array(
'custom' => array(
'rule' => array('custom', '/^[a-zA-Z0-9]{6,}$/i'), // 半角英数6文字以上
),
),
);
}
?>
> コントローラー(users_controller.php)
<?php
class UsersController extends AppController {
var $name = 'Users';
var $components = array('Auth');
function beforeFilter() {
$this->Auth->allow('add');
}
function login() {
}
function logout() {
$this->Auth->logout();
}
function add() {
if (!empty($this->data)) {
$this->User->create();
if ($this->User->save($this->data)) {
// 省略
} else {
// 省略
}
}
}
}
?>
> ビュー(add.ctp)
<div class="users form">
<h2><?php __('Add Users');?></h2>
<?php echo $this->Form->create('User');?>
<?php echo $this->Form->label('username'); ?>
<?php echo $this->Form->text('username'); ?>
<?php echo $this->Form->label('password'); ?>
<?php echo $this->Form->text('password'); ?>
<?php echo $this->Form->end(__('Add', true));?>
</div>
これで誰でもユーザ登録できるようになりました。
パスワードも自動的にハッシュ化されています。
めでたしめでたし。
とはいかず。。
入力ミス、つまりバリデーションルールにひっかかると不可解な動きをします。
バリデーションルールにひっかかるように、わざとユーザ名もパスワードも空でサブミットしてみると…
パスワード入力欄に謎の文字列が…
Authがハッシュ化したパスワードだということは予想できます。でもなにも入力していないのに…
とにかく、ハッシュ化された文字列が表示されてしまうのは異常。異常、異常!
ただ、この辺はAuthが自動的にやってくれている箇所なのでねぇ…
はッ!もしや、passwordフィールドに設定したバリデーションルールも効いていないのでは??
正解です。
password は未入力でも素通りします。
Authで取り扱うパスワードフィールドは、モデルでは制御できないのです。
【解決策】
入力時のフィールド名は「new_password」として、コントローラー内でデータを登録する直前に「password」にする。
これでモデルのバリデーションルールも有効になり、Authがハッシュ化した文字列も表示されることはなくなりました。
> モデル(user.php)
<?php
class User extends AppModel {
var $name = 'User';
var $validate = array(
'username' => array(
'notempty' => array(
'rule' => array('notempty'), // 未入力チェック
),
'isUnique' => array(
'rule' => 'isUnique', // 重複チェック
),
),
'new_password' => array(
'custom' => array(
'rule' => array('custom', '/^[a-zA-Z0-9]{6,}$/i'), // 半角英数6文字以上
),
),
);
}
?>
> コントローラー(users_controller.php)
<?php
class UsersController extends AppController {
var $name = 'Users';
var $components = array('Auth');
function beforeFilter() {
$this->Auth->allow('add');
}
function login() {
}
function logout() {
$this->Auth->logout();
}
function add() {
if (!empty($this->data)) {
$this->User->create();
$this->data['User']['password'] = $this->Auth->password($this->data['User']['new_password']);
if ($this->User->save($this->data)) {
// 省略
} else {
// 省略
}
}
}
}
?>
> ビュー(add.ctp)
<div class="users form">
<h2><?php __('Add Users');?></h2>
<?php echo $this->Form->create('User');?>
<?php echo $this->Form->label('username'); ?>
<?php echo $this->Form->text('username'); ?>
<?php echo $this->Form->label('new_password'); ?>
<?php echo $this->Form->text('new_password'); ?>
<?php echo $this->Form->end(__('Submit', true));?>
</div>
※他に何かいい方法があれば教えてください。
Comments
これだと
バリデーションルールでメッセージを表示させる際に、new_passwordなんて存在しないよとエラー文を吐かれ文字化けが発生してしまいます。
データ登録時だけでなく失敗した時も変化するようにするにはどうしたら良いでしょうか?
ビューを編集し忘れていました。問題なく済みました。
ビューを編集し忘れていました。問題なく済みました。
あ、よかったです(^^;