You are here

class CSRFAccessCheck in Zircon Profile 8

Same name in this branch
  1. 8 core/lib/Drupal/Core/Access/CsrfAccessCheck.php \Drupal\Core\Access\CsrfAccessCheck
  2. 8 core/modules/rest/src/Access/CSRFAccessCheck.php \Drupal\rest\Access\CSRFAccessCheck
Same name and namespace in other branches
  1. 8.0 core/modules/rest/src/Access/CSRFAccessCheck.php \Drupal\rest\Access\CSRFAccessCheck

Access protection against CSRF attacks.

Hierarchy

Expanded class hierarchy of CSRFAccessCheck

1 string reference to 'CSRFAccessCheck'
rest.services.yml in core/modules/rest/rest.services.yml
core/modules/rest/rest.services.yml
1 service uses CSRFAccessCheck
access_check.rest.csrf in core/modules/rest/rest.services.yml
Drupal\rest\Access\CSRFAccessCheck

File

core/modules/rest/src/Access/CSRFAccessCheck.php, line 20
Contains \Drupal\rest\Access\CSRFAccessCheck.

Namespace

Drupal\rest\Access
View source
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);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CSRFAccessCheck::$sessionConfiguration protected property The session configuration.
CSRFAccessCheck::access public function Checks access.
CSRFAccessCheck::applies public function Declares whether the access check applies to a specific route or not. Overrides AccessCheckInterface::applies
CSRFAccessCheck::__construct public function Constructs a new rest CSRF access check.