Validator.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Session;
  7. use Magento\Framework\Exception\SessionException;
  8. use Magento\Framework\Phrase;
  9. /**
  10. * Session Validator
  11. */
  12. class Validator implements ValidatorInterface
  13. {
  14. const VALIDATOR_KEY = '_session_validator_data';
  15. const VALIDATOR_HTTP_USER_AGENT_KEY = 'http_user_agent';
  16. const VALIDATOR_HTTP_X_FORWARDED_FOR_KEY = 'http_x_forwarded_for';
  17. const VALIDATOR_HTTP_VIA_KEY = 'http_via';
  18. const VALIDATOR_REMOTE_ADDR_KEY = 'remote_addr';
  19. const XML_PATH_USE_REMOTE_ADDR = 'web/session/use_remote_addr';
  20. const XML_PATH_USE_HTTP_VIA = 'web/session/use_http_via';
  21. const XML_PATH_USE_X_FORWARDED = 'web/session/use_http_x_forwarded_for';
  22. const XML_PATH_USE_USER_AGENT = 'web/session/use_http_user_agent';
  23. /**
  24. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  25. */
  26. protected $_scopeConfig;
  27. /**
  28. * @var \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress
  29. */
  30. protected $_remoteAddress;
  31. /**
  32. * @var array
  33. */
  34. protected $_skippedAgentList;
  35. /**
  36. * @var string
  37. */
  38. protected $_scopeType;
  39. /**
  40. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  41. * @param \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress
  42. * @param string $scopeType
  43. * @param array $skippedUserAgentList
  44. */
  45. public function __construct(
  46. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  47. \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress,
  48. $scopeType,
  49. array $skippedUserAgentList = []
  50. ) {
  51. $this->_scopeConfig = $scopeConfig;
  52. $this->_remoteAddress = $remoteAddress;
  53. $this->_skippedAgentList = $skippedUserAgentList;
  54. $this->_scopeType = $scopeType;
  55. }
  56. /**
  57. * Validate session
  58. *
  59. * @param SessionManagerInterface $session
  60. * @return void
  61. * @throws SessionException
  62. */
  63. public function validate(SessionManagerInterface $session)
  64. {
  65. if (!isset($_SESSION[self::VALIDATOR_KEY])) {
  66. $_SESSION[self::VALIDATOR_KEY] = $this->_getSessionEnvironment();
  67. } else {
  68. try {
  69. $this->_validate();
  70. } catch (SessionException $e) {
  71. $session->destroy(['clear_storage' => false]);
  72. // throw core session exception
  73. throw $e;
  74. }
  75. }
  76. }
  77. /**
  78. * Validate data
  79. *
  80. * @return bool
  81. * @throws SessionException
  82. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  83. */
  84. protected function _validate()
  85. {
  86. $sessionData = $_SESSION[self::VALIDATOR_KEY];
  87. $validatorData = $this->_getSessionEnvironment();
  88. if ($this->_scopeConfig->getValue(
  89. self::XML_PATH_USE_REMOTE_ADDR,
  90. $this->_scopeType
  91. ) && $sessionData[self::VALIDATOR_REMOTE_ADDR_KEY] != $validatorData[self::VALIDATOR_REMOTE_ADDR_KEY]
  92. ) {
  93. throw new SessionException(
  94. new Phrase(
  95. 'The "%1" session value is invalid. Verify and try again.',
  96. [self::VALIDATOR_REMOTE_ADDR_KEY]
  97. )
  98. );
  99. }
  100. if ($this->_scopeConfig->getValue(
  101. self::XML_PATH_USE_HTTP_VIA,
  102. $this->_scopeType
  103. ) && $sessionData[self::VALIDATOR_HTTP_VIA_KEY] != $validatorData[self::VALIDATOR_HTTP_VIA_KEY]
  104. ) {
  105. throw new SessionException(
  106. new Phrase(
  107. 'The "%1" session value is invalid. Verify and try again.',
  108. [self::VALIDATOR_HTTP_VIA_KEY]
  109. )
  110. );
  111. }
  112. $httpXForwardedKey = $sessionData[self::VALIDATOR_HTTP_X_FORWARDED_FOR_KEY];
  113. $validatorXForwarded = $validatorData[self::VALIDATOR_HTTP_X_FORWARDED_FOR_KEY];
  114. if ($this->_scopeConfig->getValue(
  115. self::XML_PATH_USE_X_FORWARDED,
  116. $this->_scopeType
  117. ) && $httpXForwardedKey != $validatorXForwarded
  118. ) {
  119. throw new SessionException(
  120. new Phrase(
  121. 'The "%1" session value is invalid. Verify and try again.',
  122. [self::VALIDATOR_HTTP_X_FORWARDED_FOR_KEY]
  123. )
  124. );
  125. }
  126. if ($this->_scopeConfig->getValue(
  127. self::XML_PATH_USE_USER_AGENT,
  128. $this->_scopeType
  129. ) && $sessionData[self::VALIDATOR_HTTP_USER_AGENT_KEY] != $validatorData[self::VALIDATOR_HTTP_USER_AGENT_KEY]
  130. ) {
  131. foreach ($this->_skippedAgentList as $agent) {
  132. if (preg_match('/' . $agent . '/iu', $validatorData[self::VALIDATOR_HTTP_USER_AGENT_KEY])) {
  133. return true;
  134. }
  135. }
  136. throw new SessionException(
  137. new Phrase(
  138. 'The "%1" session value is invalid. Verify and try again.',
  139. [self::VALIDATOR_HTTP_USER_AGENT_KEY]
  140. )
  141. );
  142. }
  143. return true;
  144. }
  145. /**
  146. * Prepare session environment data for validation
  147. *
  148. * @return array
  149. */
  150. protected function _getSessionEnvironment()
  151. {
  152. $parts = [
  153. self::VALIDATOR_REMOTE_ADDR_KEY => '',
  154. self::VALIDATOR_HTTP_VIA_KEY => '',
  155. self::VALIDATOR_HTTP_X_FORWARDED_FOR_KEY => '',
  156. self::VALIDATOR_HTTP_USER_AGENT_KEY => '',
  157. ];
  158. // collect ip data
  159. if ($this->_remoteAddress->getRemoteAddress()) {
  160. $parts[self::VALIDATOR_REMOTE_ADDR_KEY] = $this->_remoteAddress->getRemoteAddress();
  161. }
  162. if (isset($_ENV['HTTP_VIA'])) {
  163. $parts[self::VALIDATOR_HTTP_VIA_KEY] = (string)$_ENV['HTTP_VIA'];
  164. }
  165. if (isset($_ENV['HTTP_X_FORWARDED_FOR'])) {
  166. $parts[self::VALIDATOR_HTTP_X_FORWARDED_FOR_KEY] = (string)$_ENV['HTTP_X_FORWARDED_FOR'];
  167. }
  168. // collect user agent data
  169. if (isset($_SERVER['HTTP_USER_AGENT'])) {
  170. $parts[self::VALIDATOR_HTTP_USER_AGENT_KEY] = (string)$_SERVER['HTTP_USER_AGENT'];
  171. }
  172. return $parts;
  173. }
  174. }