Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Password hashed twice on edit - CakePHP

I have a user edit View. When people access this view it has the hashed password in the password block.

If you click save, it (obviously) hashes the password again, due to this being in my User model.

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

But I don't want to have it hashed twice (because it means the password has changed). I changed the edit view and added array('value' => '','autocomplete'=>'off') to the password field. Now when I save it, it saves a blank string in the database. I thought that it prevents it from doing that with the if(!empty($this->data['User']['password'])) statement in the beforeSave function.

How would I prevent the password from being double hashed?

like image 553
Bird87 ZA Avatar asked Feb 01 '13 08:02

Bird87 ZA


2 Answers

Solution is fairly simple. Simply change the if statement in beforeSave from:

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

to:

public function beforeSave($options = array()) {
    if(!empty($this->data['User']['password'])) {
        $this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
    } else {
        unset($this->data['User']['password']);
    }
    return true;
}
like image 175
Bird87 ZA Avatar answered Nov 20 '22 06:11

Bird87 ZA


Compare the hashes:

You can compare the hash saved in the database against the text in the password field. If you haven't touch the password (changed the password field), the hashes should match. Let's say your saved hash is xyz, and the hash loaded in the password hash is still untouched, xyz; in this case you don't have to rehash anything, and the hashes should remain the same.

In the other case, let's say your saved hash is xyz, but you edited the password html field to be abc; in this case you will have to rehash the new password (abc) and then replace the old one you have in the database record.

All of this can be translated in code as follows:

public function beforeSave($options = array()) {

    if (isset($this->data[$this->alias]['password'])) {

        if(isset($this->data[$this->alias]['id'])) {
            $id = $this->data[$this->alias]['id'];
            $user = $this->findById($id);
        } else {
            $id = false;
        }

        if(!$id || $this->data[$this->alias]['password'] != $user['User']['password']) {
            $passwordHasher = new SimplePasswordHasher();
            $this->data[$this->alias]['password'] = $passwordHasher->hash(
                $this->data[$this->alias]['password']
            );
        }

    }

    return true;
}

Regards, M

like image 3
Manuel Ro Avatar answered Nov 20 '22 06:11

Manuel Ro