Create a helper to generatate URLs with CSRF protection

This commit is contained in:
Dmitriy Simushev 2014-09-04 10:23:38 +00:00
parent c08ab3a456
commit cbc119382b
11 changed files with 83 additions and 58 deletions

View File

@ -24,6 +24,7 @@ use Mibew\Asset\AssetUrlGeneratorInterface;
use Mibew\Authentication\AuthenticationManagerAwareInterface;
use Mibew\Authentication\AuthenticationManagerInterface;
use Mibew\Handlebars\HandlebarsAwareInterface;
use Mibew\Handlebars\Helper\CsrfProtectedRouteHelper;
use Mibew\Handlebars\Helper\RouteHelper;
use Mibew\Routing\RouterAwareInterface;
use Mibew\Routing\RouterInterface;
@ -69,8 +70,12 @@ abstract class AbstractController implements
// Update router in the style helpers
if (!is_null($this->style) && $this->style instanceof HandlebarsAwareInterface) {
if ($this->style->getHandlebars()->hasHelper('route')) {
$this->style->getHandlebars()->getHelper('route')->setRouter($router);
$handlebars = $this->style->getHandlebars();
if ($handlebars->hasHelper('route')) {
$handlebars->getHelper('route')->setRouter($router);
}
if ($handlebars->hasHelper('csrfProtectedRoute')) {
$handlebars->getHelper('csrfProtectedRoute')->setRouter($router);
}
}
}
@ -233,6 +238,10 @@ abstract class AbstractController implements
'route',
new RouteHelper($this->getRouter())
);
$style->getHandlebars()->addHelper(
'csrfProtectedRoute',
new CsrfProtectedRouteHelper($this->getRouter())
);
}
return $style;

View File

@ -0,0 +1,61 @@
<?php
/*
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Mibew\Handlebars\Helper;
use Handlebars\Context;
use Handlebars\Template;
/**
* A helper that generates a URL based on route name and parameters list.
*
* It adds to the generated URL a token to protect from CSRF attacks.
*
* Example of usage:
* <code>
* {{csrfProtectedRoute "hello" to="world"}}
* </code>
* The code above generates URL for route named "hello" and pass parameter
* "to" equals to "world" to URL generator. CSRF token will be included to
* the parmeters list.
*/
class CsrfProtectedRouteHelper extends RouteHelper
{
/**
* {@inheritdoc}
*
* @todo Use combined arguments parser when it will be implemented in
* Handlebars.php.
*/
public function execute(Template $template, Context $context, $args, $source)
{
$named_args = $template->parseNamedArguments($args);
$positional_args = $template->parseArguments($args);
$route_name = (string)$context->get($positional_args[0]);
$parameters = array();
foreach ($named_args as $name => $parsed_arg) {
$parameters[$name] = $context->get($parsed_arg);
}
$parameters['csrf_token'] = get_csrf_token();
return $this->getRouter()->generate($route_name, $parameters);
}
}

View File

@ -1,44 +0,0 @@
<?php
/*
* This file is a part of Mibew Messenger.
*
* Copyright 2005-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Mibew\Handlebars\Helper;
use Handlebars\Context;
use Handlebars\Helper as HelperInterface;
use Handlebars\SafeString;
use Handlebars\Template;
/**
* Generates CSRF token prepared to insert in URLs.
*
* Example of usage:
* <code>
* {{csrfTokenInUrl}}
* </code>
*/
class CsrfTokenInUrlHelper implements HelperInterface
{
/**
* {@inheritdoc}
*/
public function execute(Template $template, Context $context, $args, $source)
{
return new SafeString(get_csrf_token_in_url());
}
}

View File

@ -60,7 +60,6 @@ class HelpersSet
'formatDateDiff' => (new Helper\FormatDateDiffHelper()),
'cutString' => (new Helper\CutStringHelper()),
'csrfTokenInput' => (new Helper\CsrfTokenInputHelper()),
'csrfTokenInUrl' => (new Helper\CsrfTokenInUrlHelper()),
);
}

View File

@ -50,11 +50,11 @@ function get_csrf_token_input()
return '<input name="csrf_token" type="hidden" value="' . $_SESSION['csrf_token'] . '" />';
}
function get_csrf_token_in_url()
function get_csrf_token()
{
set_csrf_token();
return "csrf_token=" . $_SESSION['csrf_token'];
return $_SESSION['csrf_token'];
}
/* set csrf token */

View File

@ -56,7 +56,7 @@
<td>{{cutString comment "30"}}</td>
<td>
<a class="removelink" id="i{{banid}}" href="{{route "ban_delete" ban_id=banid}}?{{csrfTokenInUrl}}">
<a class="removelink" id="i{{banid}}" href="{{csrfProtectedRoute "ban_delete" ban_id=banid}}">
{{l10n "remove"}}
</a>,
<a href="{{route "ban_edit" ban_id=banid}}/edit"

View File

@ -74,7 +74,7 @@
<td>
<a href="{{route "canned_message_edit" message_id=id}}" target="_blank"
onclick="this.newWindow = window.open('{{route "canned_message_edit" message_id=id}}', '', 'toolbar=0,scrollbars=1,location=0,status=1,menubar=0,width=640,height=480,resizable=1');this.newWindow.focus();this.newWindow.opener=window;return false;">{{l10n "edit"}}</a>,
<a href="{{route "canned_message_delete" message_id=id lang=../formlang group=../formgroup}}&amp;{{csrfTokenInUrl}}">{{l10n "remove"}}</a>
<a href="{{csrfProtectedRoute "canned_message_delete" message_id=id lang=../formlang group=../formgroup}}">{{l10n "remove"}}</a>
</td>
</tr>
{{else}}

View File

@ -125,7 +125,7 @@
{{#if ../canmodify}}
<td>
<a href="{{route "group_delete" group_id=groupid}}?{{csrfTokenInUrl}}" id="i{{groupid}}" class="removelink">
<a href="{{csrfProtectedRoute "group_delete" group_id=groupid}}" id="i{{groupid}}" class="removelink">
{{l10n "remove"}}
</a>
</td>

View File

@ -51,9 +51,9 @@
<td>
{{#if isDisabled}}
<a href="{{route "locale_enable" locale=code}}?{{csrfTokenInUrl}}">{{l10n "enable"}}</a>
<a href="{{csrfProtectedRoute "locale_enable" locale=code}}">{{l10n "enable"}}</a>
{{else}}
<a href="{{route "locale_disable" locale=code}}?{{csrfTokenInUrl}}">{{l10n "disable"}}</a>
<a href="{{csrfProtectedRoute "locale_disable" locale=code}}">{{l10n "disable"}}</a>
{{/if}}
</td>
</tr>

View File

@ -30,7 +30,7 @@
<div class="fvalue">
<img src="{{avatar}}" alt="cannot load avatar"/><br/>
{{#if canmodify}}
<a class="formauth" href="{{route "operator_avatar_delete" operator_id=opid}}?{{csrfTokenInUrl}}">
<a class="formauth" href="{{csrfProtectedRoute "operator_avatar_delete" operator_id=opid}}">
{{l10n "Remove avatar"}}
</a>
{{/if}}

View File

@ -111,14 +111,14 @@
{{#if ../canmodify}}
<td>
{{#if isDisabled}}
<a href="{{route "operator_enable" operator_id=operatorid}}?{{csrfTokenInUrl}}">{{l10n "enable"}}</a>
<a href="{{csrfProtectedRoute "operator_enable" operator_id=operatorid}}">{{l10n "enable"}}</a>
{{else}}
<a href="{{route "operator_disable" operator_id=operatorid}}?{{csrfTokenInUrl}}">{{l10n "disable"}}</a>
<a href="{{csrfProtectedRoute "operator_disable" operator_id=operatorid}}">{{l10n "disable"}}</a>
{{/if}}
</td>
<td>
<a class="removelink" id="i{{operatorid}}" href="{{route "operator_delete" operator_id=operatorid}}?{{csrfTokenInUrl}}">
<a class="removelink" id="i{{operatorid}}" href="{{csrfProtectedRoute "operator_delete" operator_id=operatorid}}">
{{l10n "remove"}}
</a>
</td>