vendor/symfony/security-http/Firewall.php line 74

Open in your IDE?
  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;
  11. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
  14. use Symfony\Component\HttpKernel\Event\RequestEvent;
  15. use Symfony\Component\HttpKernel\KernelEvents;
  16. use Symfony\Component\Security\Http\Firewall\ExceptionListener;
  17. use Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
  18. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  19. /**
  20. * Firewall uses a FirewallMap to register security listeners for the given
  21. * request.
  22. *
  23. * It allows for different security strategies within the same application
  24. * (a Basic authentication for the /api, and a web based authentication for
  25. * everything else for instance).
  26. *
  27. * @author Fabien Potencier <fabien@symfony.com>
  28. */
  29. class Firewall implements EventSubscriberInterface
  30. {
  31. private $map;
  32. private $dispatcher;
  33. /**
  34. * @var \SplObjectStorage<Request, ExceptionListener>
  35. */
  36. private $exceptionListeners;
  37. public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher)
  38. {
  39. $this->map = $map;
  40. $this->dispatcher = $dispatcher;
  41. $this->exceptionListeners = new \SplObjectStorage();
  42. }
  43. public function onKernelRequest(RequestEvent $event)
  44. {
  45. if (!$event->isMainRequest()) {
  46. return;
  47. }
  48. // register listeners for this firewall
  49. $listeners = $this->map->getListeners($event->getRequest());
  50. $authenticationListeners = $listeners[0];
  51. $exceptionListener = $listeners[1];
  52. $logoutListener = $listeners[2];
  53. if (null !== $exceptionListener) {
  54. $this->exceptionListeners[$event->getRequest()] = $exceptionListener;
  55. $exceptionListener->register($this->dispatcher);
  56. }
  57. // Authentication listeners are pre-sorted by SortFirewallListenersPass
  58. $authenticationListeners = function () use ($authenticationListeners, $logoutListener) {
  59. if (null !== $logoutListener) {
  60. $logoutListenerPriority = $this->getListenerPriority($logoutListener);
  61. }
  62. foreach ($authenticationListeners as $listener) {
  63. $listenerPriority = $this->getListenerPriority($listener);
  64. // Yielding the LogoutListener at the correct position
  65. if (null !== $logoutListener && $listenerPriority < $logoutListenerPriority) {
  66. yield $logoutListener;
  67. $logoutListener = null;
  68. }
  69. yield $listener;
  70. }
  71. // When LogoutListener has the lowest priority of all listeners
  72. if (null !== $logoutListener) {
  73. yield $logoutListener;
  74. }
  75. };
  76. $this->callListeners($event, $authenticationListeners());
  77. }
  78. public function onKernelFinishRequest(FinishRequestEvent $event)
  79. {
  80. $request = $event->getRequest();
  81. if (isset($this->exceptionListeners[$request])) {
  82. $this->exceptionListeners[$request]->unregister($this->dispatcher);
  83. unset($this->exceptionListeners[$request]);
  84. }
  85. }
  86. /**
  87. * {@inheritdoc}
  88. */
  89. public static function getSubscribedEvents()
  90. {
  91. return [
  92. KernelEvents::REQUEST => ['onKernelRequest', 8],
  93. KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest',
  94. ];
  95. }
  96. protected function callListeners(RequestEvent $event, iterable $listeners)
  97. {
  98. foreach ($listeners as $listener) {
  99. $listener($event);
  100. if ($event->hasResponse()) {
  101. break;
  102. }
  103. }
  104. }
  105. private function getListenerPriority(object $logoutListener): int
  106. {
  107. return $logoutListener instanceof FirewallListenerInterface ? $logoutListener->getPriority() : 0;
  108. }
  109. }