diff --git a/core/core.services.yml b/core/core.services.yml
index da2d413..e5daa04 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -368,6 +368,10 @@ services:
     arguments: ['@plugin.manager.entity']
     tags:
       - { name: access_check }
+  access_check.csrf:
+    class: Drupal\Core\Access\CsrfAccessCheck
+    tags:
+      - { name: access_check }
   maintenance_mode_subscriber:
     class: Drupal\Core\EventSubscriber\MaintenanceModeSubscriber
     tags:
diff --git a/core/lib/Drupal/Core/Access/CsrfAccessCheck.php b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
new file mode 100644
index 0000000..0cd8f3b
--- /dev/null
+++ b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Access\CsrfAccessCheck.
+ */
+
+namespace Drupal\Core\Access;
+
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Allows access to routes to be controlled by a '_csrf' parameter.
+ *
+ * To use this check, add a "csrf" GET parameter to URLs using
+ * drupal_get_token(), for which the parameter has the same value as the
+ * "_csrf" parameter in the route.
+ */
+class CsrfAccessCheck implements AccessCheckInterface {
+
+  /**
+   * Implements AccessCheckInterface::applies().
+   */
+  public function applies(Route $route) {
+    return array_key_exists('_csrf', $route->getRequirements());
+  }
+
+  /**
+   * Implements AccessCheckInterface::access().
+   */
+  public function access(Route $route, Request $request) {
+    return drupal_get_token($route->getRequirement('_csrf')) == $request->query->get('csrf');
+  }
+}
\ No newline at end of file
diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
new file mode 100644
index 0000000..75e4189
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
@@ -0,0 +1,65 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Access\CsrfAccessCheckTest.
+ */
+
+namespace Drupal\Tests\Core\Access;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Route;
+use Drupal\Core\Access\CsrfAccessCheck;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests \Drupal\Core\Access\CsrfAccessCheck.
+ */
+class CsrfAccessCheckTest extends UnitTestCase {
+
+  public static function getInfo() {
+    return array(
+      'name' => '\Drupal\Tests\Core\Access\CsrfAccessCheck',
+      'group' => 'Access'
+    );
+  }
+
+  /**
+   * Tests CsrfAccessCheck::applies().
+   */
+  public function testApplies() {
+    $applies_check = new CsrfAccessCheck();
+
+    $route = $this->getMockBuilder('Symfony\Component\Routing\Route')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $route->expects($this->any())
+      ->method('getRequirements')
+      ->will($this->returnValue(array('_csrf' => '')));
+    $res = $applies_check->applies($route);
+    $this->assertEquals(TRUE, $res);
+
+    $route = $this->getMockBuilder('Symfony\Component\Routing\Route')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $route->expects($this->any())
+      ->method('getRequirements')
+      ->will($this->returnValue(array()));
+    $res = $applies_check->applies($route);
+    $this->assertEquals(FALSE, $res);
+  }
+
+  /**
+   * Tests CsrfAccessCheck::access().
+   */
+  public function testAccess() {
+    $token_value = 'b1rd';
+    $route = new Route('/foo', array(), array('_csrf: ' . $token_value));
+    $request = new Request(array(
+      'csrf' => drupal_get_token($token_value),
+    ));
+    $access_check = new CsrfAccessCheck();
+    $access = $access_check->access($route, $request);
+    $this->assertEquals(TRUE, $access);
+  }
+}
