Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 26 |
CSRFAccessCheck | |
0.00% |
0 / 1 |
|
0.00% |
0 / 3 |
110 | |
0.00% |
0 / 26 |
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
applies | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 12 |
|||
access | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 12 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\rest\Access\CSRFAccessCheck. | |
*/ | |
namespace Drupal\rest\Access; | |
use Drupal\Core\Access\AccessCheckInterface; | |
use Drupal\Core\Access\AccessResult; | |
use Drupal\Core\Session\AccountInterface; | |
use Drupal\Core\Session\SessionConfigurationInterface; | |
use Symfony\Component\Routing\Route; | |
use Symfony\Component\HttpFoundation\Request; | |
/** | |
* Access protection against CSRF attacks. | |
*/ | |
class CSRFAccessCheck implements AccessCheckInterface { | |
/** | |
* The session configuration. | |
* | |
* @var \Drupal\Core\Session\SessionConfigurationInterface | |
*/ | |
protected $sessionConfiguration; | |
/** | |
* Constructs a new rest CSRF access check. | |
* | |
* @param \Drupal\Core\Session\SessionConfigurationInterface $session_configuration | |
* The session configuration. | |
*/ | |
public function __construct(SessionConfigurationInterface $session_configuration) { | |
$this->sessionConfiguration = $session_configuration; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function applies(Route $route) { | |
$requirements = $route->getRequirements(); | |
if (array_key_exists('_access_rest_csrf', $requirements)) { | |
if (isset($requirements['_method'])) { | |
// There could be more than one method requirement separated with '|'. | |
$methods = explode('|', $requirements['_method']); | |
// CSRF protection only applies to write operations, so we can filter | |
// out any routes that require reading methods only. | |
$write_methods = array_diff($methods, array('GET', 'HEAD', 'OPTIONS', 'TRACE')); | |
if (empty($write_methods)) { | |
return FALSE; | |
} | |
} | |
// No method requirement given, so we run this access check to be on the | |
// safe side. | |
return TRUE; | |
} | |
} | |
/** | |
* Checks access. | |
* | |
* @param \Symfony\Component\HttpFoundation\Request $request | |
* The request object. | |
* @param \Drupal\Core\Session\AccountInterface $account | |
* The currently logged in account. | |
* | |
* @return \Drupal\Core\Access\AccessResultInterface | |
* The access result. | |
*/ | |
public function access(Request $request, AccountInterface $account) { | |
$method = $request->getMethod(); | |
// This check only applies if | |
// 1. this is a write operation | |
// 2. the user was successfully authenticated and | |
// 3. the request comes with a session cookie. | |
if (!in_array($method, array('GET', 'HEAD', 'OPTIONS', 'TRACE')) | |
&& $account->isAuthenticated() | |
&& $this->sessionConfiguration->hasSession($request) | |
) { | |
$csrf_token = $request->headers->get('X-CSRF-Token'); | |
if (!\Drupal::csrfToken()->validate($csrf_token, 'rest')) { | |
return AccessResult::forbidden()->setCacheMaxAge(0); | |
} | |
} | |
// Let other access checkers decide if the request is legit. | |
return AccessResult::allowed()->setCacheMaxAge(0); | |
} | |
} |