How can I check whether the supplied CSRF token is invalid in Symfony2?

此生再无相见时 提交于 2019-12-03 11:39:27
Upvote

There is no documented way to check csrf token manually. Symfony automatically validates the presence and accuracy of this token. http://symfony.com/doc/current/book/forms.html#csrf-protection

However there is a csrf provider:

http://api.symfony.com/2.0/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.html

and

http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.html

Marks classes able to provide CSRF protection You can generate a CSRF token by using the method generateCsrfToken(). To this method you should pass a value that is unique to the page that should be secured against CSRF attacks. This value doesn't necessarily have to be secret. Implementations of this interface are responsible for adding more secret information.

If you want to secure a form submission against CSRF attacks, you could supply an "intention" string. This way you make sure that the form can only be bound to pages that are designed to handle the form, that is, that use the same intention string to validate the CSRF token with isCsrfTokenValid().

You can retrieve the provider like this

$csrf = $this->get('form.csrf_provider');

use can then use

public Boolean isCsrfTokenValid(string $intention, string $token)

Validates a CSRF token.

Parameters string $intention The intention used when generating the CSRF token string $token The token supplied by the browser

Return Value Boolean Whether the token supplied by the browser is correct

You need to finde out the intention string used by your form.

Some interesting posts on SO:

Symfony CSRF and Ajax

Symfony2 links with CSRF token

p-bizouard

In addition to artworkad, you can specify an intention:

Twig:

<form method="post">
    <input type="text" name="form_name[field]" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('form_name') }}">
</form>

PHP:

$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('form_name', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));

Or not:

Twig:

<form method="post">
    <input type="text" name="field" value="" />
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('') }}">
</form>

PHP:

$token = $request->request->get('_csrf_token');
$csrf_token = new CsrfToken('', $token);
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token));

I am not sure of this but have you tried the validator on an unmapped field:

$violations = $this->get('validator')->validatePropertyValue($entity, '_token', $form['_token']);
if (count($violations)) {
    // the property value is not valid
}

Another way (if you prefer DI) to validate token outside of controller (e.g. in listener):

/** @var Symfony\Component\Security\Csrf\CsrfTokenManagerInterface */
private $csrfTokenManager;

public __construct(CsrfTokenManagerInterface $csrfTokenManager) 
{
    $this->csrfTokenManager = $csrfTokenManager;
}

public function isValid(): bool
{
    return $this->csrfTokenManager->isTokenValid(
            new CsrfToken('authenticate', $request->getRequest()->headers->get('X-CSRF-TOKEN'))
        );
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!