5

我有一个用户编辑视图。当人们访问此视图时,它在密码块中有散列密码。

如果您单击保存,它(显然)会再次对密码进行哈希处理,因为这是在我的用户模型中。

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

但我不想让它散列两次(因为这意味着密码已更改)。我更改了编辑视图并添加array('value' => '','autocomplete'=>'off')到密码字段。现在当我保存它时,它会在数据库中保存一个空白字符串。我认为它会阻止它使用函数if(!empty($this->data['User']['password']))中的语句来执行此beforeSave操作。

如何防止密码被双重哈希?

4

5 回答 5

5

解决方案相当简单。只需将 beforeSave 中的 if 语句更改为:

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

到:

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;
}
于 2013-02-01T09:37:43.723 回答
3

比较哈希:

您可以将数据库中保存的哈希值与密码字段中的文本进行比较。如果您没有触摸密码(更改密码字段),哈希值应该匹配。假设您保存的散列是xyz,并且密码散列中加载的散列仍然保持不变,xyz; 在这种情况下,您不必重新散列任何内容,并且散列应该保持不变。

在另一种情况下,假设您保存的哈希是xyz,但您将密码 html 字段编辑为abc; 在这种情况下,您必须重新散列新密码 ( abc),然后替换数据库记录中的旧密码。

所有这些都可以用如下代码翻译:

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;
}

问候,米

于 2014-05-22T05:44:28.543 回答
1

在您的视图中使用备用字段名称(例如$this->Form->password('pwd')

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

这可以防止密码被覆盖/空白。此链接上的信用、解释和其他最佳实践

于 2013-02-01T09:46:28.650 回答
0

通常用户编辑页面与您描述的不同。如果您存储散列密码,则密码永远不会在编辑视图中返回。

如果用户想要更改他的密码,一个表单通常包含 3 个字段

  • 旧密码
  • 新密码
  • 新密码(检查它是否等于以前的密码)

然后发生的是:

  • 检查两个新密码的值是否相等
  • 散列旧密码
  • 哈希新密码
  • 检查旧密码散列是否等于数据库中的散列...如果是,旧散列将被新散列替换

在您的示例中,您无法区分散列和常规密码,因此您的代码可能永远不会在其当前状态下工作,因为散列也只是一个字符串文字。

于 2013-02-01T08:26:29.683 回答
0
public function beforeSave($options = array()) {
    if(AuthComponent::user('id') == null)
        if (isset($this->data[$this->alias]['password'])) {
            $this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
        }
        return true;
}
于 2013-11-11T07:04:37.927 回答