防止恶意用户在添加操作时更新数据

Preventing malicious users update data at add action

这是一个基本的添加操作:

public function add()
{
    $article = $this->Articles->newEntity();

    if ($this->request->is('post')) {
        $article = $this->Articles->patchEntity($article, $this->request->data);

        if ($this->Articles->save($article)) {
            $this->Flash->success('Success.');
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error('Fail.');    
        }
    }

    $this->set(compact('article'));
}

如果恶意用户在表单中注入名称为 id 的字段并将该字段的值设置为 2。由于用户这样做,id 值将在 $this->request->data 中,因此在 $this->Articles->patchEntity($article, $this->request->data) 中,此 id 将被修补,而在 $this->Articles->save($article) 中,记录 2 将被更新的创造新记录??

视情况而定。

Entity::$_accessible

如果您烘焙了模型,则不应发生这种情况,因为主键字段不会包含在定义字段的实体 _accessible 属性 中可以是 mass assigned when creating/patching entities.(这种行为最近发生了变化)

如果您烘焙了模型,那么这不应该发生,因为主键字段将在实体 _accessible 属性 中设置为不可分配,这意味着这些字段不能通过 mass assignment when creating/patching entities.

设置

如果您没有烘焙模型并且没有定义 _accessible 属性,或者向其中添加主键字段,那么是的,以防发布的数据到达补丁机制,那么这就是将会发生的事情,你将得到一个 UPDATE 而不是 INSERT.

安全组件

Security component will prevent form tampering,并拒绝修改表单的请求。如果您要使用它,那么表单数据首先不会进入 add() 方法。

还有 fieldList 选项

The fieldList option 可以在 creating/patching 实体时使用,以指定允许在实体上设置的字段。稀疏掉id字段,就不能注入了

$article = $this->Articles->patchEntity($article, $this->request->data, [
    'fieldList' => [
        'title',
        'body',
        //...
    ]
]);

最后,验证

Validation 也可以防止注入,但是这可能被认为有点靠不住。一个简单的 returns false 的自定义规则,例如,你可以创建一个额外的验证器,比如

public function validationAdd(Validator $validator) {
    return
        $this->validationDefault($validator)
            ->add('id', 'mustNotBePresent', ['rule' => function() {
                return false;
            }]);
}

然后可以在像

这样修补实体时使用
$article = $this->Articles->patchEntity($article, $this->request->data, [
    'validate' => 'add'
]);