FormProtection

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

The FormProtection Component provides protection against form data tampering.

Like all components it is configured through several configurable parameters.All of these properties can be set directly or through setter methods of thesame name in your controller’s initialize() or beforeFilter() methods.

If you are using other components that process form data in their startup()callbacks, be sure to place FormProtection Component before those componentsin your initialize() method.

Note

When using the FormProtection Component you must use the FormHelper to createyour forms. In addition, you must not override any of the fields’ “name”attributes. The FormProtection Component looks for certain indicators that arecreated and managed by the FormHelper (especially those created inView\Helper\FormHelper::create() andView\Helper\FormHelper::end()). Dynamically alteringthe fields that are submitted in a POST request (e.g. disabling, deletingor creating new fields via JavaScript) is likely to cause the form tokenvalidation to fail.

Form tampering prevention

By default the FormProtectionComponent prevents users from tampering withforms in specific ways. It will prevent the following things:

  • Form’s action (URL) cannot be modified.
  • Unknown fields cannot be added to the form.
  • Fields cannot be removed from the form.
  • Values in hidden inputs cannot be modified.

Preventing these types of tampering is accomplished by working with the FormHelperand tracking which fields are in a form. The values for hidden fields aretracked as well. All of this data is combined and turned into a hash and hiddentoken fields are automatically be inserted into forms. When a form is submitted,the FormProtectionComponent will use the POST data to build the same structureand compare the hash.

Note

The FormProtectionComponent will not prevent select options from beingadded/changed. Nor will it prevent radio options from being added/changed.

Usage

Configuring the security component is generally done in the controller’sinitialize() or beforeFilter() callbacks

Available options are:

  • validate
  • Set to false to completely skip the validation of POSTrequests, essentially turning off form validation.
  • unlockedFields
  • Set to a list of form fields to exclude from POST validation. Fields can beunlocked either in the Component, or withFormHelper::unlockField(). Fields that have been unlocked arenot required to be part of the POST and hidden unlocked fields do not havetheir values checked.
  • unlockedActions
  • Actions to exclude from POST validation checks.
  • validationFailureCallback
  • Callback to call in case of validation failure. Must be a valid Closure.Unset by default in which case exception is thrown on validation failure.

Disabling form tampering checks

  1. namespace App\Controller;
  2.  
  3. use App\Controller\AppController;
  4. use Cake\Event\EventInterface;
  5.  
  6. class WidgetsController extends AppController
  7. {
  8. public function initialize(): void
  9. {
  10. parent::initialize();
  11.  
  12. $this->loadComponent('FormProtection');
  13. }
  14.  
  15. public function beforeFilter(EventInterface $event)
  16. {
  17. parent::beforeFilter($event);
  18.  
  19. if ($this->request->getParam('prefix') === 'Admin') {
  20. $this->Security->setConfig('validate', false);
  21. }
  22. }
  23. }

The above example would disable form tampering prevention for admin prefixedroutes.

Disabling form tampering for specific actions

There may be cases where you want to disable form tampering prevention for anaction (ex. AJAX requests). You may “unlock” these actions by listing them in$this->Security->unlockedActions in your beforeFilter():

  1. namespace App\Controller;
  2.  
  3. use App\Controller\AppController;
  4. use Cake\Event\EventInterface;
  5.  
  6. class WidgetController extends AppController
  7. {
  8. public function initialize(): void
  9. {
  10. parent::initialize();
  11. $this->loadComponent('Security');
  12. }
  13.  
  14. public function beforeFilter(EventInterface $event)
  15. {
  16. parent::beforeFilter($event);
  17.  
  18. $this->Security->setConfig('unlockedActions', ['edit']);
  19. }
  20. }

This example would disable all security checks for the edit action.

Handling validation failure through callbacks

If form protection validation fails it will result in a 400 error by default.You can configure this behavior by setting the validationFailureCallbackconfiguration option to a callback function in the controller.

By configuring a callback method you can customize how the failure handling processworks:

  1. public function beforeFilter(EventInterface $event)
  2. {
  3. parent::beforeFilter($event);
  4.  
  5. $this->FormProtection->setConfig(
  6. 'validationFailureCallback',
  7. function (BadRequestException $exception) {
  8. // You can either return a response instance or throw the exception
  9. // received as argument.
  10. }
  11. );
  12. }