3 namespace Drupal\Core\Access;
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Core\PrivateKey;
7 use Drupal\Core\Session\MetadataBag;
8 use Drupal\Core\Site\Settings;
11 * Generates and validates CSRF tokens.
13 * @see \Drupal\Tests\Core\Access\CsrfTokenGeneratorTest
15 class CsrfTokenGenerator {
18 * The private key service.
20 * @var \Drupal\Core\PrivateKey
22 protected $privateKey;
25 * The session metadata bag.
27 * @var \Drupal\Core\Session\MetadataBag
29 protected $sessionMetadata;
32 * Constructs the token generator.
34 * @param \Drupal\Core\PrivateKey $private_key
35 * The private key service.
36 * @param \Drupal\Core\Session\MetadataBag $session_metadata
37 * The session metadata bag.
39 public function __construct(PrivateKey $private_key, MetadataBag $session_metadata) {
40 $this->privateKey = $private_key;
41 $this->sessionMetadata = $session_metadata;
45 * Generates a token based on $value, the user session, and the private key.
47 * The generated token is based on the session of the current user. Normally,
48 * anonymous users do not have a session, so the generated token will be
49 * different on every page request. To generate a token for users without a
50 * session, manually start a session prior to calling this function.
52 * @param string $value
53 * (optional) An additional value to base the token on.
56 * A 43-character URL-safe token for validation, based on the token seed,
57 * the hash salt provided by Settings::getHashSalt(), and the
58 * 'drupal_private_key' configuration variable.
60 * @see \Drupal\Core\Site\Settings::getHashSalt()
61 * @see \Symfony\Component\HttpFoundation\Session\SessionInterface::start()
63 public function get($value = '') {
64 $seed = $this->sessionMetadata->getCsrfTokenSeed();
66 $seed = Crypt::randomBytesBase64();
67 $this->sessionMetadata->setCsrfTokenSeed($seed);
70 return $this->computeToken($seed, $value);
74 * Validates a token based on $value, the user session, and the private key.
76 * @param string $token
77 * The token to be validated.
78 * @param string $value
79 * (optional) An additional value to base the token on.
82 * TRUE for a valid token, FALSE for an invalid token.
84 public function validate($token, $value = '') {
85 $seed = $this->sessionMetadata->getCsrfTokenSeed();
90 return Crypt::hashEquals($this->computeToken($seed, $value), $token);
94 * Generates a token based on $value, the token seed, and the private key.
97 * The per-session token seed.
98 * @param string $value
99 * (optional) An additional value to base the token on.
102 * A 43-character URL-safe token for validation, based on the token seed,
103 * the hash salt provided by Settings::getHashSalt(), and the
104 * 'drupal_private_key' configuration variable.
106 * @see \Drupal\Core\Site\Settings::getHashSalt()
108 protected function computeToken($seed, $value = '') {
109 return Crypt::hmacBase64($value, $seed . $this->privateKey->get() . Settings::getHashSalt());