Commit e75ac464 authored by catch's avatar catch
Browse files

Issue #2133439 by damiankloip: Dynamically create token value string based on route path.

parent a83becbd
......@@ -51,7 +51,7 @@ public function appliesTo() {
public function access(Route $route, Request $request, AccountInterface $account) {
// If this is the controller request, check CSRF access as normal.
if ($request->attributes->get('_controller_request')) {
return $this->csrfToken->validate($request->query->get('token'), $route->getRequirement('_csrf_token')) ? static::ALLOW : static::KILL;
return $this->csrfToken->validate($request->query->get('token'), $request->attributes->get('_system_path')) ? static::ALLOW : static::KILL;
}
// Otherwise, this could be another requested access check that we don't
......
......@@ -39,9 +39,14 @@ function __construct(CsrfTokenGenerator $csrf_token) {
*/
public function processOutbound(Route $route, array &$parameters) {
if ($route->hasRequirement('_csrf_token')) {
$path = $route->getPath();
// Replace the path parameters with values from the parameters array.
foreach ($parameters as $param => $value) {
$path = str_replace("{{$param}}", $value, $path);
}
// Adding this to the parameters means it will get merged into the query
// string when the route is compiled.
$parameters['token'] = $this->csrfToken->get($route->getRequirement('_csrf_token'));
$parameters['token'] = $this->csrfToken->get($path);
}
}
......
......@@ -14,7 +14,7 @@
use Drupal\Tests\UnitTestCase;
/**
* Tests the CSRF access checker..
* Tests the CSRF access checker.
*
* @group Drupal
* @group Access
......@@ -75,13 +75,12 @@ public function testAppliesTo() {
public function testAccessTokenPass() {
$this->csrfToken->expects($this->once())
->method('validate')
->with('test_query', 'test')
->with('test_query', '/test-path')
->will($this->returnValue(TRUE));
$route = new Route('', array(), array('_csrf_token' => 'test'));
$request = new Request(array(
'token' => 'test_query',
));
$route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
$request = Request::create('/test-path?token=test_query');
$request->attributes->set('_system_path', '/test-path');
// Set the _controller_request flag so tokens are validated.
$request->attributes->set('_controller_request', TRUE);
......@@ -94,13 +93,12 @@ public function testAccessTokenPass() {
public function testAccessTokenFail() {
$this->csrfToken->expects($this->once())
->method('validate')
->with('test_query', 'test')
->with('test_query', '/test-path')
->will($this->returnValue(FALSE));
$route = new Route('', array(), array('_csrf_token' => 'test'));
$request = new Request(array(
'token' => 'test_query',
));
$route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
$request = Request::create('/test-path?token=test_query');
$request->attributes->set('_system_path', '/test-path');
// Set the _controller_request flag so tokens are validated.
$request->attributes->set('_controller_request', TRUE);
......@@ -116,7 +114,7 @@ public function testAccessTokenMissAny() {
$this->csrfToken->expects($this->never())
->method('validate');
$route = new Route('', array(), array('_csrf_token' => 'test'));
$route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
$request = new Request(array(
'token' => 'test_query',
));
......@@ -133,7 +131,7 @@ public function testAccessTokenMissAll() {
$this->csrfToken->expects($this->never())
->method('validate');
$route = new Route('', array(), array('_csrf_token' => 'test'), array('_access_mode' => 'ALL'));
$route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'), array('_access_mode' => 'ALL'));
$request = new Request(array(
'token' => 'test_query',
));
......
......@@ -58,7 +58,7 @@ public function testProcessOutboundNoRequirement() {
$this->csrfToken->expects($this->never())
->method('get');
$route = new Route('');
$route = new Route('/test-path');
$parameters = array();
$this->processor->processOutbound($route, $parameters);
......@@ -72,10 +72,10 @@ public function testProcessOutboundNoRequirement() {
public function testProcessOutbound() {
$this->csrfToken->expects($this->once())
->method('get')
->with('test')
->with('/test-path')
->will($this->returnValue('test_token'));
$route = new Route('', array(), array('_csrf_token' => 'test'));
$route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
$parameters = array();
$this->processor->processOutbound($route, $parameters);
......@@ -84,4 +84,34 @@ public function testProcessOutbound() {
$this->assertSame($parameters['token'], 'test_token');
}
/**
* Tests the processOutbound() method with a dynamic path and one replacement.
*/
public function testProcessOutboundDynamicOne() {
$this->csrfToken->expects($this->once())
->method('get')
->with('/test-path/100')
->will($this->returnValue('test_token'));
$route = new Route('/test-path/{slug}', array(), array('_csrf_token' => 'TRUE'));
$parameters = array('slug' => 100);
$this->assertNull($this->processor->processOutbound($route, $parameters));
}
/**
* Tests the processOutbound() method with two parameter replacements.
*/
public function testProcessOutboundDynamicTwo() {
$this->csrfToken->expects($this->once())
->method('get')
->with('/100/test-path/test')
->will($this->returnValue('test_token'));
$route = new Route('{slug_1}/test-path/{slug_2}', array(), array('_csrf_token' => 'TRUE'));
$parameters = array('slug_1' => 100, 'slug_2' => 'test');
$this->assertNull($this->processor->processOutbound($route, $parameters));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment