New in Symfony 7.1: IsCsrfTokenValid Attribute
May 7, 2024 • Published by Javier Eguiluz
Symfony 7.1 is backed by:
Contributed by
Yassine Guedidi
in #52961
and #54443.
CSRF (Cross-site Request Forgery) attacks are used by malicious users to make your legitimate users submit data unknowingly. In Symfony we provide full protection against CSRF attacks thanks to the SecurityCsrf component.
The following is a common code snippet used in controllers that extend Symfony's
AbstractController
to check that the CSRF token of the form is valid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class BlogPostController extends AbstractController
{
// ...
public function delete(): Response
{
if (!$this->isCsrfTokenValid('delete_example', $request->request->getString('_token'))) {
throw new BadRequestHttpException('This token is invalid');
}
// ...
}
}
In Symfony 7.1 we're introducing a new #[IsCsrfTokenValid]
attribute to make
this code simpler:
1 2 3 4 5 6 7 8 9 10 11 12 13
// ...
use Symfony\Component\Security\Http\Attribute\IsCsrfTokenValid;
class BlogPostController
{
// ...
#[IsCsrfTokenValid('delete_example')]
public function delete(): Response
{
// ...
}
}
Another common need is to check multiple similar CSRF tokens. For example, in a listing of blog posts, each one has a slightly different delete form:
1 2 3 4 5 6 7
{% for post in blog_posts %}
{# ... #}
<form action="{{ path('post_delete', {post: post.id}) }}" method="POST">
<input type="hidden" name="_token" value="{{ csrf_token('delete-post-' ~ post.id) }}">
</form>
{% endfor %}
This can also be solved with the #[IsCsrfTokenValid]
attribute because it
supports expressions compatible with the ExpressionLanguage component:
1 2 3 4 5 6 7 8 9 10 11 12 13
// ...
use Symfony\Component\ExpressionLanguage\Expression;
class BlogPostController
{
// ...
#[IsCsrfTokenValid(new Expression('"delete-post-" ~ args["post"].id'))]
public function delete(Request $request, Post $post): Response
{
// ...
}
}
Help the Symfony project!
As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.
Comments are closed.
To ensure that comments stay relevant, they are closed for old posts.
- https://github.com/symfony/demo/blob/main/src/Controller/Admin/BlogController.php#L168
- https://github.com/symfony/maker-bundle/blob/main/src/Resources/skeleton/crud/controller/Controller.tpl.php#L85
What should I do if the CSRF token is not valid?