CSRF
The Centum\Http\Csrf
namespace exists to prevent cross-site request forgery attacks that could exist in HTML forms.
This component comes in three parts: Generator
, Storage
, and Validator
.
Centum\Http\Csrf\Generator
implements Centum\Interfaces\Http\Csrf\GeneratorInterface
.
Centum\Http\Csrf\Storage
implements Centum\Interfaces\Http\Csrf\StorageInterface
.
Centum\Http\Csrf\Validator
implements Centum\Interfaces\Http\Csrf\ValidatorInterface
.
Centum\Http\Csrf\Generator(
);
Centum\Http\Csrf\Storage(
Centum\Interfaces\Http\SessionInterface $session,
Centum\Interfaces\Http\Csrf\GeneratorInterface $generator
);
Centum\Http\Csrf\Validator(
Centum\Interfaces\Http\RequestInterface $request,
Centum\Interfaces\Http\Csrf\StorageInterface $storage
);
The Centum\Http\Csrf
namespace works by generating and storing a random string in a Centum\Interfaces\Http\SessionInterface
object and making this value available for use in a <form>
. By comparing the value submitted by the user and the known value from the Session, we can validate whether the POST request is genuine or not.
Wherever a POST request requires CSRF protection, the current token value can be obtained from a Storage
object and injected into the view:
use Centum\Interfaces\Http\Csrf\GeneratorInterface;
use Centum\Interfaces\Http\SessionInterface;
/** @var SessionInterface $session */
/** @var GeneratorInterface $generator */
$csrfStorage = new Storage($session, $generator);
$csrfValue = $csrfStorage->get();
<form>
<input type="hidden" name="csrf" value="<?php echo $csrfValue; ?>">
<!-- rest of the form -->
</form>
If you’re using Twig, you can use the Centum CSRF Twig extension by simply calling the csrf()
function somewhere in the form:
<form>
{{ csrf() }}
<!-- rest of the form -->
</form>
The CSRF Twig extension also provides the csrfValue()
function that returns the raw CSRF value which is useful when dealing with AJAX form submissions:
$.post(
{
url: "/update-password",
data: {
"newPassword": $("#newPassword").val(),
"newPasswordConfirm": $("#newPasswordConfirm").val(),
"csrf": "{{ csrfValue() }}"
}
}
);
Regardless of how the CSRF token is placed, ValidatorInterface::validate()
must be called at the top of your Form’s constructor method to validate it:
namespace App\Web\Forms;
use Centum\Interfaces\Http\Csrf\ValidatorInterface;
use Centum\Interfaces\Http\FormInterface;
class SubmissionForm implements FormInterface
{
public function __construct(ValidatorInterface $csrfValidator)
{
$csrfValidator->validate();
// ...
}
}
Values are generated with the GeneratorInterface::generate()
method:
use Centum\Interfaces\Http\Csrf\GeneratorInterface;
/** @var GeneratorInterface $csrfGenerator */
$newValue = $csrfGenerator->generate();
Values can be removed from the Session with the StorageInterface::reset()
method:
use Centum\Interfaces\Http\Csrf\StorageInterface;
/** @var StorageInterface $csrfStorage */
$csrfStorage->reset();