vendor/symfony/security-http/Firewall/AccessListener.php line 34

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\Security\Http\Firewall;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpKernel\Event\RequestEvent;
  13. use Symfony\Component\Security\Core\Authentication\Token\NullToken;
  14. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  15. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  16. use Symfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
  17. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  18. use Symfony\Component\Security\Http\AccessMapInterface;
  19. use Symfony\Component\Security\Http\Event\LazyResponseEvent;
  20. /**
  21. * AccessListener enforces access control rules.
  22. *
  23. * @author Fabien Potencier <fabien@symfony.com>
  24. *
  25. * @final
  26. */
  27. class AccessListener extends AbstractListener
  28. {
  29. private TokenStorageInterface $tokenStorage;
  30. private AccessDecisionManagerInterface $accessDecisionManager;
  31. private AccessMapInterface $map;
  32. public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, bool $exceptionOnNoToken = false)
  33. {
  34. if (false !== $exceptionOnNoToken) {
  35. throw new \LogicException(sprintf('Argument $exceptionOnNoToken of "%s()" must be set to "false".', __METHOD__));
  36. }
  37. $this->tokenStorage = $tokenStorage;
  38. $this->accessDecisionManager = $accessDecisionManager;
  39. $this->map = $map;
  40. }
  41. public function supports(Request $request): ?bool
  42. {
  43. [$attributes] = $this->map->getPatterns($request);
  44. $request->attributes->set('_access_control_attributes', $attributes);
  45. if ($attributes && [AuthenticatedVoter::PUBLIC_ACCESS] !== $attributes) {
  46. return true;
  47. }
  48. return null;
  49. }
  50. /**
  51. * Handles access authorization.
  52. *
  53. * @throws AccessDeniedException
  54. */
  55. public function authenticate(RequestEvent $event): void
  56. {
  57. $request = $event->getRequest();
  58. $attributes = $request->attributes->get('_access_control_attributes');
  59. $request->attributes->remove('_access_control_attributes');
  60. if (!$attributes || (
  61. [AuthenticatedVoter::PUBLIC_ACCESS] === $attributes && $event instanceof LazyResponseEvent
  62. )) {
  63. return;
  64. }
  65. $token = $this->tokenStorage->getToken() ?? new NullToken();
  66. if (!$this->accessDecisionManager->decide($token, $attributes, $request, true)) {
  67. throw $this->createAccessDeniedException($request, $attributes);
  68. }
  69. }
  70. private function createAccessDeniedException(Request $request, array $attributes): AccessDeniedException
  71. {
  72. $exception = new AccessDeniedException();
  73. $exception->setAttributes($attributes);
  74. $exception->setSubject($request);
  75. return $exception;
  76. }
  77. public static function getPriority(): int
  78. {
  79. return -255;
  80. }
  81. }