diff --git a/core/core.services.yml b/core/core.services.yml index 9b9c80b..439cb7d 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -498,7 +498,7 @@ services: arguments: ['@state'] csrf_token: class: Drupal\Core\Access\CsrfTokenGenerator - arguments: ['@private_key'] + arguments: ['@private_key', '@session_manager'] access_manager: class: Drupal\Core\Access\AccessManager arguments: ['@router.route_provider', '@url_generator', '@paramconverter_manager'] diff --git a/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php b/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php index fef3d74..3fd060e 100644 --- a/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php +++ b/core/lib/Drupal/Core/Access/CsrfTokenGenerator.php @@ -10,6 +10,7 @@ use Drupal\Component\Utility\Crypt; use Drupal\Core\PrivateKey; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Session\SessionManagerInterface; /** * Generates and validates CSRF tokens. @@ -26,13 +27,21 @@ class CsrfTokenGenerator { protected $privateKey; /** + * The session manager. + * + * @var \Drupal\Core\Session\SessionManagerInterface + */ + protected $sessionManager; + + /** * Constructs the token generator. * * @param \Drupal\Core\PrivateKey $private_key * The private key service. */ - public function __construct(PrivateKey $private_key) { + public function __construct(PrivateKey $private_key, SessionManagerInterface $session_manager) { $this->privateKey = $private_key; + $this->sessionManager = $session_manager; } /** @@ -55,11 +64,7 @@ public function __construct(PrivateKey $private_key) { * @see \Drupal\Core\Session\SessionManager::start() */ public function get($value = '') { - if (empty($_SESSION['csrf_token_seed'])) { - $_SESSION['csrf_token_seed'] = Crypt::randomBytesBase64(); - } - - return Crypt::hmacBase64($value, $_SESSION['csrf_token_seed'] . $this->privateKey->get() . drupal_get_hash_salt()); + return Crypt::hmacBase64($value, $this->sessionManager->getCsrfTokenSeed(TRUE) . $this->privateKey->get() . drupal_get_hash_salt()); } /** @@ -74,11 +79,11 @@ public function get($value = '') { * TRUE for a valid token, FALSE for an invalid token. */ public function validate($token, $value = '') { - if (empty($_SESSION['csrf_token_seed'])) { + if (!$seed = $this->sessionManager->getCsrfTokenSeed()) { return FALSE; } - return $token === Crypt::hmacBase64($value, $_SESSION['csrf_token_seed'] . $this->privateKey->get() . drupal_get_hash_salt()); + return $token === Crypt::hmacBase64($value, $seed . $this->privateKey->get() . drupal_get_hash_salt()); } } diff --git a/core/lib/Drupal/Core/Session/SessionManager.php b/core/lib/Drupal/Core/Session/SessionManager.php index 365ff28..5b3fd1d 100644 --- a/core/lib/Drupal/Core/Session/SessionManager.php +++ b/core/lib/Drupal/Core/Session/SessionManager.php @@ -287,6 +287,17 @@ public function enable() { } /** + * {@inheritdoc} + */ + public function getCsrfTokenSeed($generate_if_empty = FALSE) { + if ($generate_if_empty && !isset($_SESSION['csrf_token_seed'])) { + $_SESSION['csrf_token_seed'] = Crypt::randomBytesBase64(); + } + + return isset($_SESSION['csrf_token_seed']) ? $_SESSION['csrf_token_seed'] : NULL; + } + + /** * Returns whether the current PHP process runs on CLI. * * Command line clients do not support cookies nor sessions. diff --git a/core/lib/Drupal/Core/Session/SessionManagerInterface.php b/core/lib/Drupal/Core/Session/SessionManagerInterface.php index 346bc0d..7ad79bd 100644 --- a/core/lib/Drupal/Core/Session/SessionManagerInterface.php +++ b/core/lib/Drupal/Core/Session/SessionManagerInterface.php @@ -77,4 +77,12 @@ public function disable(); */ public function enable(); + /** + * Gets the CSRF token seed for this session. + * + * @return string + * The unique token seed for this session. + */ + public function getCsrfTokenSeed(); + }