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