Исключение InvalidCsrfTokenException
Исключение InvalidCsrfTokenException относится к подсистеме безопасности Symfony и выбрасывается тогда, когда CSRF-токен, переданный в запросе, отсутствует, просрочен или не совпадает с ожидаемым значением. Класс наследуется от AuthenticationException и реализует интерфейс AuthenticationExceptionInterface, поэтому стандартный слушатель безопасности может перехватить его и перенаправить пользователя на форму входа. Чаще всего исключение возникает при отправке POST-формы без скрытого поля _token или при истёкшей сессии.
Синтаксис
throw new InvalidCsrfTokenException($message, $code, $previous);
Пример
Давайте создадим форму с CSRF-защитой и посмотрим, какое исключение возникнет при отправке запроса без токена:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
class FormController extends AbstractController
{
#[Route('/form', name: 'form_submit', methods: ['POST'])]
public function submit(Request $request, CsrfTokenManagerInterface $csrfManager): Response
{
$token = $request->request->get('_token', '');
$csrf = new CsrfToken('form_submit', $token);
if (!$csrfManager->isTokenValid($csrf)) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
return new Response('form accepted');
}
}
?>
Если отправить POST-запрос на адрес /form без поля _token, выполнение прервётся выбросом исключения. В браузере отобразится стандартная страница ошибки Symfony.
Пример
Давайте перехватим исключение в контроллере и вернём понятный ответ вместо страницы ошибки:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
class FormController extends AbstractController
{
#[Route('/form', name: 'form_submit', methods: ['POST'])]
public function submit(Request $request, CsrfTokenManagerInterface $csrfManager): Response
{
$token = $request->request->get('_token', '');
$csrf = new CsrfToken('form_submit', $token);
try {
if (!$csrfManager->isTokenValid($csrf)) {
throw new InvalidCsrfTokenException('Invalid CSRF token.');
}
return new Response('form accepted');
} catch (InvalidCsrfTokenException $e) {
return new Response($e->getMessage(), Response::HTTP_BAD_REQUEST);
}
}
}
?>
Результат выполнения кода при недействительном токене:
"Invalid CSRF token."
Смотрите также
-
исключение
AuthenticationException,
базовый класс для ошибок аутентификации -
исключение
AccessDeniedException,
которое выбрасывается при недостатке прав -
метод
getMessage,
который возвращает текст исключения -
исключение
HttpException,
которое связывает ошибку с HTTP-статусом