FormProtection

class FormProtection(ComponentCollection $collection, array $config = [])

FormProtection 组件提供对表单数据篡改的保护。

与所有组件一样,它通过几个可配置参数进行配置。所有这些属性都可以直接设置,也可以通过您控制器中 initialize()beforeFilter() 方法中相同名称的设置方法设置。

如果您使用其他组件,这些组件在其 startup() 回调中处理表单数据,请确保在您的 initialize() 方法中将 FormProtection 组件放在这些组件之前。

注意

使用 FormProtection 组件时,您必须使用 FormHelper 来创建表单。此外,您不能覆盖任何字段的“name”属性。FormProtection 组件会查找由 FormHelper 创建和管理的某些指示器(尤其是那些在 Cake\View\Helper\FormHelper::create()Cake\View\Helper\FormHelper::end() 中创建的)。动态更改在 POST 请求中提交的字段,例如通过 JavaScript 禁用、删除或创建新字段,可能会导致表单令牌验证失败。

防止表单篡改

默认情况下,FormProtectionComponent 会阻止用户以特定方式篡改表单。它将阻止以下操作:

  • 无法修改表单的 action(URL)。

  • 无法向表单添加未知字段。

  • 无法从表单中删除字段。

  • 无法修改隐藏输入的值。

通过与 FormHelper 协作并跟踪表单中的哪些字段来实现对这些类型篡改的阻止。隐藏字段的值也会被跟踪。所有这些数据都会被组合并转换成一个散列,隐藏令牌字段也会自动插入表单。表单提交时,FormProtectionComponent 会使用 POST 数据构建相同的结构并比较散列。

注意

FormProtectionComponent 不会阻止添加/更改 select 选项。它也不会阻止添加/更改单选按钮选项。

用法

通常在控制器的 initialize()beforeFilter() 回调中配置表单保护组件。

可用的选项包括:

validate

设置为 false 以完全跳过对 POST 请求的验证,本质上是关闭表单验证。

unlockedFields

设置为表单字段列表,将其从 POST 验证中排除。可以单独在组件中,或通过 FormHelper::unlockField() 解锁字段。已解锁的字段不需要作为 POST 的一部分,并且隐藏的解锁字段不会检查其值。

unlockedActions

要从 POST 验证检查中排除的操作。

validationFailureCallback

验证失败时要调用的回调。必须是一个有效的闭包。默认情况下取消设置,在这种情况下,验证失败时会抛出异常。

禁用表单篡改检查

namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\EventInterface;

class WidgetsController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();

        $this->loadComponent('FormProtection');
    }

    public function beforeFilter(EventInterface $event)
    {
        parent::beforeFilter($event);

        if ($this->request->getParam('prefix') === 'Admin') {
            $this->FormProtection->setConfig('validate', false);
        }
    }
}

上面的示例将为具有 admin 前缀的路由禁用表单篡改防御。

为特定操作禁用表单篡改

在某些情况下,您可能希望为某个操作禁用表单篡改防御(例如 AJAX 请求)。您可以通过在您的 beforeFilter() 中将它们列在 $this->FormProtection->setConfig('unlockedActions', ['edit']); 中来“解锁”这些操作。

namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\EventInterface;

class WidgetController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();
        $this->loadComponent('FormProtection');
    }

    public function beforeFilter(EventInterface $event)
    {
        parent::beforeFilter($event);

        $this->FormProtection->setConfig('unlockedActions', ['edit']);
    }
}

此示例将为 edit 操作禁用所有安全检查。

通过回调处理验证失败

如果表单保护验证失败,默认情况下会导致 400 错误。您可以通过在控制器中将 validationFailureCallback 配置选项设置为回调函数来配置此行为。

通过配置回调方法,您可以自定义故障处理过程的工作方式。

public function beforeFilter(EventInterface $event)
{
    parent::beforeFilter($event);

    $this->FormProtection->setConfig(
        'validationFailureCallback',
        function (BadRequestException $exception) {
            // You can either return a response instance or throw the exception
            // received as argument.
        }
    );
}