1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
namespace carono\checksum; |
5
|
|
|
|
6
|
|
|
use yii\helpers\ArrayHelper; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Class Request |
10
|
|
|
* |
11
|
|
|
* @property mixed checksumKey |
12
|
|
|
* @package carono\checksum |
13
|
|
|
*/ |
14
|
|
|
class Request extends \yii\web\Request |
15
|
|
|
{ |
16
|
|
|
public $checksumParam = '_checksum'; |
17
|
|
|
public $enableChecksumValidation = true; |
18
|
|
|
public $redefineActiveField = true; |
19
|
|
|
public $activeFormClasses = [ |
20
|
|
|
\yii\widgets\ActiveForm::class, |
21
|
|
|
\yii\bootstrap\ActiveForm::class, |
22
|
|
|
\carono\checksum\ActiveForm::class |
23
|
|
|
]; |
24
|
|
|
protected $_checksumKey; |
25
|
|
|
|
26
|
|
|
public function getChecksumKey() |
27
|
|
|
{ |
28
|
|
|
return $this->_checksumKey ?: hash("sha256", $this->cookieValidationKey); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
public function setChecksumKey($value) |
32
|
|
|
{ |
33
|
|
|
$this->_checksumKey = $value; |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
public function init() |
37
|
|
|
{ |
38
|
|
|
parent::init(); |
39
|
|
|
if ($this->redefineActiveField) { |
40
|
|
|
$behavior = ['as caronoChecksumBehavior' => ChecksumBehavior::class]; |
41
|
|
|
foreach ($this->activeFormClasses as $class) { |
42
|
|
|
if (class_exists($class)) { |
43
|
|
|
\Yii::$container->set($class, $behavior); |
44
|
|
|
} |
45
|
|
|
} |
46
|
|
|
} |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
public function checksumIsEnabled() |
50
|
|
|
{ |
51
|
|
|
return $this->enableChecksumValidation; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @param null $clientSuppliedToken |
56
|
|
|
* @return bool |
57
|
|
|
*/ |
58
|
|
|
public function validateCsrfToken($clientSuppliedToken = null) |
59
|
|
|
{ |
60
|
|
|
if ($this->isPost && $this->checksumIsEnabled()) { |
61
|
|
|
$post = $this->post(); |
62
|
|
|
$checksum = ArrayHelper::remove($post, $this->checksumParam); |
63
|
|
|
$stack = $this->getStackByChecksum($checksum); |
64
|
|
|
$postPartials = Checksum::formKeyPartials($post); |
65
|
|
|
$stackPartials = Checksum::formKeyPartials($stack); |
66
|
|
|
foreach (array_diff($stackPartials, $postPartials) as $lostPartial) { |
67
|
|
|
list($formName, $attribute) = explode('=', $lostPartial); |
68
|
|
|
$post[$formName][$attribute] = ''; |
69
|
|
|
} |
70
|
|
|
if (!Checksum::validate($post, $checksum, $this->checksumKey)) { |
71
|
|
|
return false; |
72
|
|
|
} |
73
|
|
|
$this->clearStack(); |
74
|
|
|
} |
75
|
|
|
return parent::validateCsrfToken($clientSuppliedToken); |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* @return string |
80
|
|
|
*/ |
81
|
|
|
protected function getStackKey() |
82
|
|
|
{ |
83
|
|
|
return self::className() . $this->checksumParam; |
|
|
|
|
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param $widgetId |
88
|
|
|
* @param $stack |
89
|
|
|
* @return string |
90
|
|
|
*/ |
91
|
|
|
public function setStack($stack) |
92
|
|
|
{ |
93
|
|
|
$checksum = Checksum::calculate($stack, $this->checksumKey); |
94
|
|
|
$key = $this->getStackKey(); |
95
|
|
|
$data = $this->getStack(); |
96
|
|
|
$data[$checksum] = $stack; |
97
|
|
|
\Yii::$app->session->set($key, $data); |
98
|
|
|
return $checksum; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
public function clearStack() |
102
|
|
|
{ |
103
|
|
|
return \Yii::$app->session->set($this->getStackKey(), []); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @return mixed |
108
|
|
|
*/ |
109
|
|
|
public function getStack() |
110
|
|
|
{ |
111
|
|
|
return \Yii::$app->session->get($this->getStackKey(), []); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param $checksum |
116
|
|
|
* @return array |
117
|
|
|
*/ |
118
|
|
|
public function getStackByChecksum($checksum) |
119
|
|
|
{ |
120
|
|
|
return ArrayHelper::getValue($this->getStack(), $checksum); |
121
|
|
|
} |
122
|
|
|
} |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.