vendor/symfony/security-http/Firewall/ChannelListener.php line 29

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\Firewall;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\HttpFoundation\RedirectResponse;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Symfony\Component\HttpKernel\Event\RequestEvent;
  15. use Symfony\Component\Security\Http\AccessMapInterface;
  16. use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
  17. /**
  18. * ChannelListener switches the HTTP protocol based on the access control
  19. * configuration.
  20. *
  21. * @author Fabien Potencier <fabien@symfony.com>
  22. *
  23. * @final
  24. */
  25. class ChannelListener extends AbstractListener
  26. {
  27. private $map;
  28. private $authenticationEntryPoint = null;
  29. private $logger;
  30. private $httpPort;
  31. private $httpsPort;
  32. public function __construct(AccessMapInterface $map, /* ?LoggerInterface */ $logger = null, /* int */ $httpPort = 80, /* int */ $httpsPort = 443)
  33. {
  34. if ($logger instanceof AuthenticationEntryPointInterface) {
  35. trigger_deprecation('symfony/security-http', '5.4', 'The "$authenticationEntryPoint" argument of "%s()" is deprecated.', __METHOD__);
  36. $this->authenticationEntryPoint = $logger;
  37. $nrOfArgs = \func_num_args();
  38. $logger = $nrOfArgs > 2 ? func_get_arg(2) : null;
  39. $httpPort = $nrOfArgs > 3 ? func_get_arg(3) : 80;
  40. $httpsPort = $nrOfArgs > 4 ? func_get_arg(4) : 443;
  41. }
  42. if (null !== $logger && !$logger instanceof LoggerInterface) {
  43. throw new \TypeError(sprintf('Argument "$logger" of "%s()" must be instance of "%s", "%s" given.', __METHOD__, LoggerInterface::class, get_debug_type($logger)));
  44. }
  45. $this->map = $map;
  46. $this->logger = $logger;
  47. $this->httpPort = $httpPort;
  48. $this->httpsPort = $httpsPort;
  49. }
  50. /**
  51. * Handles channel management.
  52. */
  53. public function supports(Request $request): ?bool
  54. {
  55. [, $channel] = $this->map->getPatterns($request);
  56. if ('https' === $channel && !$request->isSecure()) {
  57. if (null !== $this->logger) {
  58. if ('https' === $request->headers->get('X-Forwarded-Proto')) {
  59. $this->logger->info('Redirecting to HTTPS. ("X-Forwarded-Proto" header is set to "https" - did you set "trusted_proxies" correctly?)');
  60. } elseif (str_contains($request->headers->get('Forwarded', ''), 'proto=https')) {
  61. $this->logger->info('Redirecting to HTTPS. ("Forwarded" header is set to "proto=https" - did you set "trusted_proxies" correctly?)');
  62. } else {
  63. $this->logger->info('Redirecting to HTTPS.');
  64. }
  65. }
  66. return true;
  67. }
  68. if ('http' === $channel && $request->isSecure()) {
  69. if (null !== $this->logger) {
  70. $this->logger->info('Redirecting to HTTP.');
  71. }
  72. return true;
  73. }
  74. return false;
  75. }
  76. public function authenticate(RequestEvent $event)
  77. {
  78. $request = $event->getRequest();
  79. $event->setResponse($this->createRedirectResponse($request));
  80. }
  81. private function createRedirectResponse(Request $request): RedirectResponse
  82. {
  83. if (null !== $this->authenticationEntryPoint) {
  84. return $this->authenticationEntryPoint->start($request);
  85. }
  86. $scheme = $request->isSecure() ? 'http' : 'https';
  87. if ('http' === $scheme && 80 != $this->httpPort) {
  88. $port = ':'.$this->httpPort;
  89. } elseif ('https' === $scheme && 443 != $this->httpsPort) {
  90. $port = ':'.$this->httpsPort;
  91. } else {
  92. $port = '';
  93. }
  94. $qs = $request->getQueryString();
  95. if (null !== $qs) {
  96. $qs = '?'.$qs;
  97. }
  98. $url = $scheme.'://'.$request->getHost().$port.$request->getBaseUrl().$request->getPathInfo().$qs;
  99. return new RedirectResponse($url, 301);
  100. }
  101. }