3
votes

Let's say I have a user registration and I'm using the Auth component (/user/register is allowed of course).

The problem is if I need to set a minLength validation rule in the model, it doesn't work since the Auth component hashes the password therefore it's always more than my minlength password and it passes even if it's blank.

How do I fix this issue? Thanks in advance!

2
That is strange. minLength validation rule works perfectly for me with Auth component. I have two validation rules for the password field: minLength and notEmpty. - bancer
@bancer: That definitely has not been my experience. What version of cake are you using? What does your validation code look like? - mikermcneil
@mikermcneil: it was cake 1.2. Part of the $validate array: 'password' => array( 'minLength' => array( 'rule' => array('minLength', '8') ), 'notEmpty' => array( 'rule' => 'notEmpty', 'required' => true ) ), 'confirm_password' => array( 'minLength' => array( 'rule' => array('minLength', '8'), 'required' => true ), 'notEmpty' => array( 'rule' => 'notEmpty' ), 'comparePasswords' => array( 'rule' => '_comparePasswords' // Protected function below ), ). - bancer
@mikermcneil: passwords comparison method: protected function _comparePasswords(){ $hashedConfirmPassword = Security::hash($this->data['User']['confirm_password'], null, true); if($this->data['User']['password'] == $hashedConfirmPassword){ return true; }else{ return false; } } - bancer

2 Answers

6
votes

Essentially, you have to rename the password field (for example, to "pw") to prevent the Auth component from hashing it automatically. Then, if the password passes the validation rules, hash it and save the hash under the password key. This is usually done in the beforeFilter() callback as this article describes.

It is also possible to validate the data and hash the password in the controller. This practice is generally discouraged, but it might be a little easier to wrap your head around if you're just starting out with CakePHP.

// this code would go after: if (!empty($this->data)  
//               and before: $this->User->save($this->data)

// validate the data
$this->User->set($this->data);
if ($this->User->validates()) {

    // hash the password
    $password_hash = $this->Auth->password($this->data['User']['pw'];
    $this->data['User']['password'] = $password_hash;
}
0
votes

hmm.. here's what I consider best practice: Left the password field as is. Include a second password field 'pw2' so the user can re-type the password. Advantages:

  • prevent user typo
  • Auth won't hash pw2. In the model, you can write a custom validation method for password (because you need to check if the 2 passwords are the same too)
var $validate = array(
  'password' => array(
    'rule' => array('checkPwd')
  )
);
function checkPwd($check) {
  if(!isset($this->data[$this->alias]['password']) || 
     !isset($this->data[$this->alias]['pw2']))
     return 'Where are the passwords?';
  if($this->data[$this->alias]['password'] !== 
    Security::hash($this->data[$this->alias]['pw2'],null,true))
    return 'Passwords are not the same';
  if(strlen($this->data[$this->alias]['pw2']))<10)
    return 'Password not long enough';
  return true;
}

One little thing, in the form view, set the 'value'=>'' for both passwords fields.