From 2048cf6d35955cc276f3b698789139d08986400c Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 27 Sep 2013 09:37:01 +0200 Subject: [PATCH] [Form] Deprecated the CSRF implementation and added an optional dependency to the Security CSRF sub-component instead --- UPGRADE-3.0.md | 7 ++++ src/Symfony/Bridge/Twig/Form/TwigRenderer.php | 6 +-- .../Templating/Helper/FormHelper.php | 2 +- .../Helper/FormHelperDivLayoutTest.php | 2 +- .../Helper/FormHelperTableLayoutTest.php | 2 +- src/Symfony/Component/Form/CHANGELOG.md | 8 +++- .../Form/Extension/Csrf/CsrfExtension.php | 18 ++++----- .../CsrfProvider/CsrfProviderInterface.php | 37 ++++-------------- .../CsrfTokenGeneratorAdapter.php | 26 +++++++++++++ .../Csrf/CsrfProvider/DefaultCsrfProvider.php | 5 +++ .../Csrf/CsrfProvider/SessionCsrfProvider.php | 5 +++ .../EventListener/CsrfValidationListener.php | 22 +++++------ .../Csrf/Type/FormTypeCsrfExtension.php | 39 ++++++++++++------- .../Templating/TemplatingExtension.php | 6 +-- src/Symfony/Component/Form/FormRenderer.php | 18 ++++----- .../Component/Form/FormRendererInterface.php | 8 ++-- .../Form/Tests/AbstractDivLayoutTest.php | 2 +- .../Form/Tests/AbstractLayoutTest.php | 8 ++-- .../Form/Tests/AbstractTableLayoutTest.php | 2 +- .../CsrfValidationListenerTest.php | 9 +++-- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 32 +++++++-------- src/Symfony/Component/Form/composer.json | 4 +- 22 files changed, 154 insertions(+), 114 deletions(-) create mode 100644 src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md index 85cb84a8cc..be37fabc2c 100644 --- a/UPGRADE-3.0.md +++ b/UPGRADE-3.0.md @@ -168,6 +168,13 @@ UPGRADE FROM 2.x to 3.0 `ChoiceListInterface::getChoicesForValues()` and `ChoiceListInterface::getValuesForChoices()` should be sufficient. + * The interface `Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface` + and all of its implementations were removed. Use the new interface + `Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface` instead. + + * The options "csrf_provider" and "intention" were renamed to "csrf_token_generator" + and "csrf_token_id". + ### FrameworkBundle diff --git a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php index 72798d103f..5727f626cc 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php @@ -12,7 +12,7 @@ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRenderer; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; +use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; /** * @author Bernhard Schussek @@ -24,9 +24,9 @@ class TwigRenderer extends FormRenderer implements TwigRendererInterface */ private $engine; - public function __construct(TwigRendererEngineInterface $engine, CsrfProviderInterface $csrfProvider = null) + public function __construct(TwigRendererEngineInterface $engine, CsrfTokenGeneratorInterface $csrfTokenGenerator = null) { - parent::__construct($engine, $csrfProvider); + parent::__construct($engine, $csrfTokenGenerator); $this->engine = $engine; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php index 060a6ce6bf..7bfa1e72bf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php @@ -247,7 +247,7 @@ class FormHelper extends Helper * Check the token in your action using the same intention. * * - * $csrfProvider = $this->get('form.csrf_provider'); + * $csrfProvider = $this->get('security.csrf.token_generator'); * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php index 75f12ed789..fa526d0aea 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php @@ -46,7 +46,7 @@ class FormHelperDivLayoutTest extends AbstractDivLayoutTest )); return array_merge(parent::getExtensions(), array( - new TemplatingExtension($this->engine, $this->csrfProvider, array( + new TemplatingExtension($this->engine, $this->csrfTokenGenerator, array( 'FrameworkBundle:Form', )), )); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php index e052c6f4e4..5a917f66a6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php @@ -46,7 +46,7 @@ class FormHelperTableLayoutTest extends AbstractTableLayoutTest )); return array_merge(parent::getExtensions(), array( - new TemplatingExtension($this->engine, $this->csrfProvider, array( + new TemplatingExtension($this->engine, $this->csrfTokenGenerator, array( 'FrameworkBundle:Form', 'FrameworkBundle:FormTable', )), diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index a696c7be9a..0e15c157ae 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -1,9 +1,15 @@ CHANGELOG ========= +2.4.0 +----- + + * moved CSRF implementation to the new Security CSRF sub-component + * deprecated CsrfProviderInterface and its implementations + * deprecated options "csrf_provider" and "intention" in favor of the new options "csrf_token_generator" and "csrf_token_id" 2.3.0 ------- +----- * deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php index f9d9e40aa8..bdaa94fe36 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php +++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Form\Extension\Csrf; use Symfony\Component\Form\Extension\Csrf\Type; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\AbstractExtension; +use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; use Symfony\Component\Translation\TranslatorInterface; /** @@ -24,9 +24,9 @@ use Symfony\Component\Translation\TranslatorInterface; class CsrfExtension extends AbstractExtension { /** - * @var CsrfProviderInterface + * @var CsrfTokenGeneratorInterface */ - private $csrfProvider; + private $tokenGenerator; /** * @var TranslatorInterface @@ -41,13 +41,13 @@ class CsrfExtension extends AbstractExtension /** * Constructor. * - * @param CsrfProviderInterface $csrfProvider The CSRF provider - * @param TranslatorInterface $translator The translator for translating error messages. - * @param null|string $translationDomain The translation domain for translating. + * @param CsrfTokenGeneratorInterface $tokenGenerator The CSRF token generator + * @param TranslatorInterface $translator The translator for translating error messages + * @param null|string $translationDomain The translation domain for translating */ - public function __construct(CsrfProviderInterface $csrfProvider, TranslatorInterface $translator = null, $translationDomain = null) + public function __construct(CsrfTokenGeneratorInterface $tokenGenerator, TranslatorInterface $translator = null, $translationDomain = null) { - $this->csrfProvider = $csrfProvider; + $this->tokenGenerator = $tokenGenerator; $this->translator = $translator; $this->translationDomain = $translationDomain; } @@ -58,7 +58,7 @@ class CsrfExtension extends AbstractExtension protected function loadTypeExtensions() { return array( - new Type\FormTypeCsrfExtension($this->csrfProvider, true, '_token', $this->translator, $this->translationDomain), + new Type\FormTypeCsrfExtension($this->tokenGenerator, true, '_token', $this->translator, $this->translationDomain), ); } } diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php index 7143b130c8..1f10f56b68 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php +++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php @@ -11,39 +11,16 @@ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; +use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; + /** - * Marks classes able to provide CSRF protection - * - * You can generate a CSRF token by using the method generateCsrfToken(). To - * this method you should pass a value that is unique to the page that should - * be secured against CSRF attacks. This value doesn't necessarily have to be - * secret. Implementations of this interface are responsible for adding more - * secret information. - * - * If you want to secure a form submission against CSRF attacks, you could - * supply an "intention" string. This way you make sure that the form can only - * be submitted to pages that are designed to handle the form, that is, that use - * the same intention string to validate the CSRF token with isCsrfTokenValid(). + * Alias interface of {@link CsrfTokenGeneratorInterface}. * * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use + * {@link CsrfTokenGeneratorInterface} instead. */ -interface CsrfProviderInterface +interface CsrfProviderInterface extends CsrfTokenGeneratorInterface { - /** - * Generates a CSRF token for a page of your application. - * - * @param string $intention Some value that identifies the action intention - * (i.e. "authenticate"). Doesn't have to be a secret value. - */ - public function generateCsrfToken($intention); - - /** - * Validates a CSRF token. - * - * @param string $intention The intention used when generating the CSRF token - * @param string $token The token supplied by the browser - * - * @return Boolean Whether the token supplied by the browser is correct - */ - public function isCsrfTokenValid($intention, $token); } diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php new file mode 100644 index 0000000000..07af17d237 --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; + +use Symfony\Component\Security\Csrf\CsrfTokenGenerator; + +/** + * Adapter for using the new token generator with the old interface. + * + * @since 2.4 + * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. + */ +class CsrfTokenGeneratorAdapter extends CsrfTokenGenerator implements CsrfProviderInterface +{ +} diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php index 5354886cba..9fb971f966 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php +++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php @@ -18,6 +18,11 @@ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; * user-defined secret value to secure the CSRF token. * * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use + * {@link \Symfony\Component\Security\Csrf\CsrfTokenGenerator} in + * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage} + * instead. */ class DefaultCsrfProvider implements CsrfProviderInterface { diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php index ea1fa58547..84381adfc8 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php +++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php @@ -20,6 +20,11 @@ use Symfony\Component\HttpFoundation\Session\Session; * @see DefaultCsrfProvider * * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use + * {@link \Symfony\Component\Security\Csrf\CsrfTokenGenerator} in + * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage} + * instead. */ class SessionCsrfProvider extends DefaultCsrfProvider { diff --git a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php index 547e9d756c..70665f0fb7 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php +++ b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php @@ -15,7 +15,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; +use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; use Symfony\Component\Translation\TranslatorInterface; /** @@ -30,20 +30,20 @@ class CsrfValidationListener implements EventSubscriberInterface private $fieldName; /** - * The provider for generating and validating CSRF tokens - * @var CsrfProviderInterface + * The generator for CSRF tokens + * @var CsrfTokenGeneratorInterface */ - private $csrfProvider; + private $tokenGenerator; /** - * A text mentioning the intention of the CSRF token + * A text mentioning the tokenId of the CSRF token * * Validation of the token will only succeed if it was generated in the - * same session and with the same intention. + * same session and with the same tokenId. * * @var string */ - private $intention; + private $tokenId; /** * The message displayed in case of an error. @@ -68,11 +68,11 @@ class CsrfValidationListener implements EventSubscriberInterface ); } - public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) + public function __construct($fieldName, CsrfTokenGeneratorInterface $tokenGenerator, $tokenId, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) { $this->fieldName = $fieldName; - $this->csrfProvider = $csrfProvider; - $this->intention = $intention; + $this->tokenGenerator = $tokenGenerator; + $this->tokenId = $tokenId; $this->errorMessage = $errorMessage; $this->translator = $translator; $this->translationDomain = $translationDomain; @@ -84,7 +84,7 @@ class CsrfValidationListener implements EventSubscriberInterface $data = $event->getData(); if ($form->isRoot() && $form->getConfig()->getOption('compound')) { - if (!isset($data[$this->fieldName]) || !$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) { + if (!isset($data[$this->fieldName]) || !$this->tokenGenerator->isCsrfTokenValid($this->tokenId, $data[$this->fieldName])) { $errorMessage = $this->errorMessage; if (null !== $this->translator) { diff --git a/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php b/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php index 5fb2444262..1958c0f266 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/src/Symfony/Component/Form/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -12,12 +12,13 @@ namespace Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\AbstractTypeExtension; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; +use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; +use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; use Symfony\Component\Translation\TranslatorInterface; /** @@ -26,9 +27,9 @@ use Symfony\Component\Translation\TranslatorInterface; class FormTypeCsrfExtension extends AbstractTypeExtension { /** - * @var CsrfProviderInterface + * @var CsrfTokenGeneratorInterface */ - private $defaultCsrfProvider; + private $defaultTokenGenerator; /** * @var Boolean @@ -50,9 +51,9 @@ class FormTypeCsrfExtension extends AbstractTypeExtension */ private $translationDomain; - public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) + public function __construct(CsrfTokenGeneratorInterface $defaultTokenGenerator, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) { - $this->defaultCsrfProvider = $defaultCsrfProvider; + $this->defaultTokenGenerator = $defaultTokenGenerator; $this->defaultEnabled = $defaultEnabled; $this->defaultFieldName = $defaultFieldName; $this->translator = $translator; @@ -74,8 +75,8 @@ class FormTypeCsrfExtension extends AbstractTypeExtension $builder ->addEventSubscriber(new CsrfValidationListener( $options['csrf_field_name'], - $options['csrf_provider'], - $options['intention'], + $options['csrf_token_generator'], + $options['csrf_token_id'], $options['csrf_message'], $this->translator, $this->translationDomain @@ -94,7 +95,7 @@ class FormTypeCsrfExtension extends AbstractTypeExtension { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getFormFactory(); - $data = $options['csrf_provider']->generateCsrfToken($options['intention']); + $data = $options['csrf_token_generator']->generateCsrfToken($options['csrf_token_id']); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, @@ -109,12 +110,24 @@ class FormTypeCsrfExtension extends AbstractTypeExtension */ public function setDefaultOptions(OptionsResolverInterface $resolver) { + // BC clause for the "intention" option + $csrfTokenId = function (Options $options) { + return $options['intention']; + }; + + // BC clause for the "csrf_provider" option + $csrfTokenGenerator = function (Options $options) { + return $options['csrf_provider']; + }; + $resolver->setDefaults(array( - 'csrf_protection' => $this->defaultEnabled, - 'csrf_field_name' => $this->defaultFieldName, - 'csrf_provider' => $this->defaultCsrfProvider, - 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', - 'intention' => 'unknown', + 'csrf_protection' => $this->defaultEnabled, + 'csrf_field_name' => $this->defaultFieldName, + 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', + 'csrf_token_generator' => $csrfTokenGenerator, + 'csrf_token_id' => $csrfTokenId, + 'csrf_provider' => $this->defaultTokenGenerator, + 'intention' => 'unknown', )); } diff --git a/src/Symfony/Component/Form/Extension/Templating/TemplatingExtension.php b/src/Symfony/Component/Form/Extension/Templating/TemplatingExtension.php index 573cb518d4..e3b239873e 100644 --- a/src/Symfony/Component/Form/Extension/Templating/TemplatingExtension.php +++ b/src/Symfony/Component/Form/Extension/Templating/TemplatingExtension.php @@ -13,7 +13,7 @@ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Form\FormRenderer; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; +use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; use Symfony\Component\Templating\PhpEngine; use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper; @@ -24,10 +24,10 @@ use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper; */ class TemplatingExtension extends AbstractExtension { - public function __construct(PhpEngine $engine, CsrfProviderInterface $csrfProvider = null, array $defaultThemes = array()) + public function __construct(PhpEngine $engine, CsrfTokenGeneratorInterface $csrfTokenGenerator = null, array $defaultThemes = array()) { $engine->addHelpers(array( - new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfProvider)) + new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenGenerator)) )); } } diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php index 09b010563f..59ccc0c31a 100644 --- a/src/Symfony/Component/Form/FormRenderer.php +++ b/src/Symfony/Component/Form/FormRenderer.php @@ -13,7 +13,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; +use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; /** * Renders a form into HTML using a rendering engine. @@ -30,9 +30,9 @@ class FormRenderer implements FormRendererInterface private $engine; /** - * @var CsrfProviderInterface + * @var CsrfTokenGeneratorInterface */ - private $csrfProvider; + private $csrfTokenGenerator; /** * @var array @@ -49,10 +49,10 @@ class FormRenderer implements FormRendererInterface */ private $variableStack = array(); - public function __construct(FormRendererEngineInterface $engine, CsrfProviderInterface $csrfProvider = null) + public function __construct(FormRendererEngineInterface $engine, CsrfTokenGeneratorInterface $csrfTokenGenerator = null) { $this->engine = $engine; - $this->csrfProvider = $csrfProvider; + $this->csrfTokenGenerator = $csrfTokenGenerator; } /** @@ -74,13 +74,13 @@ class FormRenderer implements FormRendererInterface /** * {@inheritdoc} */ - public function renderCsrfToken($intention) + public function renderCsrfToken($tokenId) { - if (null === $this->csrfProvider) { - throw new BadMethodCallException('CSRF token can only be generated if a CsrfProviderInterface is injected in the constructor.'); + if (null === $this->csrfTokenGenerator) { + throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenGeneratorInterface is injected in FormRenderer::__construct().'); } - return $this->csrfProvider->generateCsrfToken($intention); + return $this->csrfTokenGenerator->generateCsrfToken($tokenId); } /** diff --git a/src/Symfony/Component/Form/FormRendererInterface.php b/src/Symfony/Component/Form/FormRendererInterface.php index 848e7125ca..7cf24c0b00 100644 --- a/src/Symfony/Component/Form/FormRendererInterface.php +++ b/src/Symfony/Component/Form/FormRendererInterface.php @@ -73,20 +73,20 @@ interface FormRendererInterface * * * - * Check the token in your action using the same intention. + * Check the token in your action using the same token ID. * * - * $csrfProvider = $this->get('form.csrf_provider'); + * $csrfProvider = $this->get('security.csrf.token_generator'); * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } * * - * @param string $intention The intention of the protected action + * @param string $tokenId The ID of the CSRF token * * @return string A CSRF token */ - public function renderCsrfToken($intention); + public function renderCsrfToken($tokenId); /** * Makes a technical name human readable. diff --git a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php index ee9ed8f2a6..c40e3e5a89 100644 --- a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php @@ -471,7 +471,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest public function testCsrf() { - $this->csrfProvider->expects($this->any()) + $this->csrfTokenGenerator->expects($this->any()) ->method('generateCsrfToken') ->will($this->returnValue('foo&bar')); diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index d2ed7711ba..c68895a643 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -17,7 +17,7 @@ use Symfony\Component\Form\Extension\Csrf\CsrfExtension; abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase { - protected $csrfProvider; + protected $csrfTokenGenerator; protected function setUp() { @@ -27,7 +27,7 @@ abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormInteg \Locale::setDefault('en'); - $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->csrfTokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); parent::setUp(); } @@ -35,13 +35,13 @@ abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormInteg protected function getExtensions() { return array( - new CsrfExtension($this->csrfProvider), + new CsrfExtension($this->csrfTokenGenerator), ); } protected function tearDown() { - $this->csrfProvider = null; + $this->csrfTokenGenerator = null; parent::tearDown(); } diff --git a/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php index 5c91195169..adcb440cc7 100644 --- a/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractTableLayoutTest.php @@ -336,7 +336,7 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest public function testCsrf() { - $this->csrfProvider->expects($this->any()) + $this->csrfTokenGenerator->expects($this->any()) ->method('generateCsrfToken') ->will($this->returnValue('foo&bar')); diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 7f2220af72..b3e45ab984 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -19,13 +19,14 @@ class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { protected $dispatcher; protected $factory; - protected $csrfProvider; + protected $tokenGenerator; + protected $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); - $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->tokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); $this->form = $this->getBuilder('post') ->setDataMapper($this->getDataMapper()) ->getForm(); @@ -35,7 +36,7 @@ class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { $this->dispatcher = null; $this->factory = null; - $this->csrfProvider = null; + $this->tokenGenerator = null; $this->form = null; } @@ -65,7 +66,7 @@ class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase $data = "XP4HUzmHPi"; $event = new FormEvent($this->form, $data); - $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown', 'Invalid.'); + $validation = new CsrfValidationListener('csrf', $this->tokenGenerator, 'unknown', 'Invalid.'); $validation->preSubmit($event); // Validate accordingly diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 0a1f0dc481..ccd7dccbca 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -37,7 +37,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $csrfProvider; + protected $tokenGenerator; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -46,7 +46,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase protected function setUp() { - $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->tokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); parent::setUp(); @@ -54,7 +54,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase protected function tearDown() { - $this->csrfProvider = null; + $this->tokenGenerator = null; $this->translator = null; parent::tearDown(); @@ -63,7 +63,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase protected function getExtensions() { return array_merge(parent::getExtensions(), array( - new CsrfExtension($this->csrfProvider, $this->translator), + new CsrfExtension($this->tokenGenerator, $this->translator), )); } @@ -123,7 +123,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase public function testGenerateCsrfToken() { - $this->csrfProvider->expects($this->once()) + $this->tokenGenerator->expects($this->once()) ->method('generateCsrfToken') ->with('%INTENTION%') ->will($this->returnValue('token')); @@ -131,7 +131,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -153,7 +153,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase */ public function testValidateTokenOnSubmitIfRootAndCompound($valid) { - $this->csrfProvider->expects($this->once()) + $this->tokenGenerator->expects($this->once()) ->method('isCsrfTokenValid') ->with('%INTENTION%', 'token') ->will($this->returnValue($valid)); @@ -161,7 +161,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -182,13 +182,13 @@ class FormTypeCsrfExtensionTest extends TypeTestCase public function testFailIfRootAndCompoundAndTokenMissing() { - $this->csrfProvider->expects($this->never()) + $this->tokenGenerator->expects($this->never()) ->method('isCsrfTokenValid'); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -209,7 +209,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase public function testDontValidateTokenIfCompoundButNoRoot() { - $this->csrfProvider->expects($this->never()) + $this->tokenGenerator->expects($this->never()) ->method('isCsrfTokenValid'); $form = $this->factory @@ -217,7 +217,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase ->add($this->factory ->createNamedBuilder('form', 'form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -233,13 +233,13 @@ class FormTypeCsrfExtensionTest extends TypeTestCase public function testDontValidateTokenIfRootButNotCompound() { - $this->csrfProvider->expects($this->never()) + $this->tokenGenerator->expects($this->never()) ->method('isCsrfTokenValid'); $form = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => false, )); @@ -269,7 +269,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase public function testsTranslateCustomErrorMessage() { - $this->csrfProvider->expects($this->once()) + $this->tokenGenerator->expects($this->once()) ->method('isCsrfTokenValid') ->with('%INTENTION%', 'token') ->will($this->returnValue(false)); @@ -282,7 +282,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'csrf_message' => 'Foobar', 'intention' => '%INTENTION%', 'compound' => true, diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index dda5959c9a..87905eaa69 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -27,8 +27,8 @@ "symfony/http-foundation": "~2.2" }, "suggest": { - "symfony/validator": "", - "symfony/http-foundation": "" + "symfony/validator": "For form validation.", + "symfony/security-csrf": "For protecting forms against CSRF attacks." }, "autoload": { "psr-0": { "Symfony\\Component\\Form\\": "" }