LazyFirewallContext.php 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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\Bundle\SecurityBundle\Security;
  11. use Symfony\Component\HttpKernel\Event\RequestEvent;
  12. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
  13. use Symfony\Component\Security\Http\Event\LazyResponseEvent;
  14. use Symfony\Component\Security\Http\Firewall\ExceptionListener;
  15. use Symfony\Component\Security\Http\Firewall\FirewallListenerInterface;
  16. use Symfony\Component\Security\Http\Firewall\LogoutListener;
  17. /**
  18. * Lazily calls authentication listeners when actually required by the access listener.
  19. *
  20. * @author Nicolas Grekas <p@tchwork.com>
  21. */
  22. class LazyFirewallContext extends FirewallContext
  23. {
  24. private $tokenStorage;
  25. public function __construct(iterable $listeners, ?ExceptionListener $exceptionListener, ?LogoutListener $logoutListener, ?FirewallConfig $config, TokenStorage $tokenStorage)
  26. {
  27. parent::__construct($listeners, $exceptionListener, $logoutListener, $config);
  28. $this->tokenStorage = $tokenStorage;
  29. }
  30. public function getListeners(): iterable
  31. {
  32. return [$this];
  33. }
  34. public function __invoke(RequestEvent $event)
  35. {
  36. $listeners = [];
  37. $request = $event->getRequest();
  38. $lazy = $request->isMethodCacheable();
  39. foreach (parent::getListeners() as $listener) {
  40. if (!$lazy || !$listener instanceof FirewallListenerInterface) {
  41. $listeners[] = $listener;
  42. $lazy = $lazy && $listener instanceof FirewallListenerInterface;
  43. } elseif (false !== $supports = $listener->supports($request)) {
  44. $listeners[] = [$listener, 'authenticate'];
  45. $lazy = null === $supports;
  46. }
  47. }
  48. if (!$lazy) {
  49. foreach ($listeners as $listener) {
  50. $listener($event);
  51. if ($event->hasResponse()) {
  52. return;
  53. }
  54. }
  55. return;
  56. }
  57. $this->tokenStorage->setInitializer(function () use ($event, $listeners) {
  58. $event = new LazyResponseEvent($event);
  59. foreach ($listeners as $listener) {
  60. $listener($event);
  61. }
  62. });
  63. }
  64. }