<?php
namespace AppBundle\Listener;
use ApiBundle\ApiBundle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage;
use Twig\Environment;
class CSRFListener
{
private $container;
private $twig;
private $csrfTokenManager;
public function __construct(ContainerInterface $container, CsrfTokenManagerInterface $csrfTokenManager, Environment $twig)
{
$this->container = $container;
$this->csrfTokenManager = $csrfTokenManager;
$this->twig = $twig;
}
public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if (HttpKernelInterface::MAIN_REQUEST != $event->getRequestType()) {
return;
}
if ('POST' !== $request->getMethod()) {
return;
}
if (0 === stripos($request->getPathInfo(), ApiBundle::API_PREFIX)) {
return;
}
if (0 === stripos($request->getPathInfo(), '/mapi')) {
return;
}
if (0 === stripos($request->getPathInfo(), '/hls')) {
return;
}
if (0 === stripos($request->getPathInfo(), '/callback')) {
return;
}
$whiteList = $this->container->hasParameter('route_white_list') ? $this->container->getParameter('route_white_list') : [];
if (in_array($request->getPathInfo(), $whiteList)) {
return;
}
if ($request->isXmlHttpRequest()) {
$token = $request->headers->get('X-CSRF-Token');
} else {
$token = $request->request->get('_csrf_token', '');
}
if (0 === stripos($request->getPathInfo(), '/admin/app/package_update/2792/begin_upgrade') || 0 === stripos($request->getPathInfo(), '/admin/app/package_update/check/newest/code/TRAININGMAIN')) {
$storage = new NativeSessionTokenStorage();
$newToken = new CsrfToken('site', $token);
if ($newToken->getValue() == $token) {
return;
}
}
$request->request->remove('_csrf_token');
$isTokenValid = $this->csrfTokenManager->isTokenValid(new CsrfToken('site', $token));
if ($isTokenValid) {
return;
}
$response = new Response($this->twig->render('default/message.html.twig', [
'type' => 'error',
'message' => $this->container->get('translator')->trans('页面已过期,请重新提交数据!'),
'goto' => '',
'duration' => 0,
]), 403);
$event->setResponse($response);
}
}