CsrfValidator.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. namespace Magento\Framework\App\Request;
  8. use Magento\Framework\App\ActionInterface;
  9. use Magento\Framework\App\Area;
  10. use Magento\Framework\App\CsrfAwareActionInterface;
  11. use Magento\Framework\App\RequestInterface;
  12. use Magento\Framework\App\State as AppState;
  13. use Magento\Framework\Data\Form\FormKey\Validator as FormKeyValidator;
  14. use Magento\Framework\Controller\Result\RedirectFactory;
  15. use Magento\Framework\App\Request\Http as HttpRequest;
  16. use Magento\Framework\Exception\LocalizedException;
  17. use Magento\Framework\Phrase;
  18. /**
  19. * Validate request for being CSRF protected.
  20. */
  21. class CsrfValidator implements ValidatorInterface
  22. {
  23. /**
  24. * @var FormKeyValidator
  25. */
  26. private $formKeyValidator;
  27. /**
  28. * @var RedirectFactory
  29. */
  30. private $redirectFactory;
  31. /**
  32. * @var AppState
  33. */
  34. private $appState;
  35. /**
  36. * @param FormKeyValidator $formKeyValidator
  37. * @param RedirectFactory $redirectFactory
  38. * @param AppState $appState
  39. */
  40. public function __construct(
  41. FormKeyValidator $formKeyValidator,
  42. RedirectFactory $redirectFactory,
  43. AppState $appState
  44. ) {
  45. $this->formKeyValidator = $formKeyValidator;
  46. $this->redirectFactory = $redirectFactory;
  47. $this->appState = $appState;
  48. }
  49. /**
  50. * @param HttpRequest $request
  51. * @param ActionInterface $action
  52. *
  53. * @return bool
  54. */
  55. private function validateRequest(
  56. HttpRequest $request,
  57. ActionInterface $action
  58. ): bool {
  59. $valid = null;
  60. if ($action instanceof CsrfAwareActionInterface) {
  61. $valid = $action->validateForCsrf($request);
  62. }
  63. if ($valid === null) {
  64. $valid = !$request->isPost()
  65. || $request->isAjax()
  66. || $this->formKeyValidator->validate($request);
  67. }
  68. return $valid;
  69. }
  70. /**
  71. * @param HttpRequest $request
  72. * @param ActionInterface $action
  73. *
  74. * @return InvalidRequestException
  75. */
  76. private function createException(
  77. HttpRequest $request,
  78. ActionInterface $action
  79. ): InvalidRequestException {
  80. $exception = null;
  81. if ($action instanceof CsrfAwareActionInterface) {
  82. $exception = $action->createCsrfValidationException($request);
  83. }
  84. if (!$exception) {
  85. $response = $this->redirectFactory->create()
  86. ->setRefererOrBaseUrl()
  87. ->setHttpResponseCode(302);
  88. $messages = [
  89. new Phrase('Invalid Form Key. Please refresh the page.'),
  90. ];
  91. $exception = new InvalidRequestException($response, $messages);
  92. }
  93. return $exception;
  94. }
  95. /**
  96. * @inheritDoc
  97. */
  98. public function validate(
  99. RequestInterface $request,
  100. ActionInterface $action
  101. ): void {
  102. try {
  103. $areaCode = $this->appState->getAreaCode();
  104. } catch (LocalizedException $exception) {
  105. $areaCode = null;
  106. }
  107. if ($request instanceof HttpRequest
  108. && in_array(
  109. $areaCode,
  110. [Area::AREA_FRONTEND, Area::AREA_ADMINHTML],
  111. true
  112. )
  113. ) {
  114. $valid = $this->validateRequest($request, $action);
  115. if (!$valid) {
  116. throw $this->createException($request, $action);
  117. }
  118. }
  119. }
  120. }