瀏覽代碼

[Form] Implemented FormFactory::buildDefault() to ease the use of the new CSRF implementation without the DIC

Bernhard Schussek 14 年之前
父節點
當前提交
d017970867

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml

@@ -24,7 +24,7 @@
         </service>
 
     	<!-- FieldFactory -->
-        <service id="form.field_factory" class="%form.field_factory.class%" public="false">
+        <service id="form.field_factory" class="%form.field_factory.class%">
         	<!-- All services with tag "form.field_factory.guesser" are inserted here by AddFieldFactoryGuessersPass -->
         </service>
 

+ 3 - 0
src/Symfony/Component/Form/CsrfProvider/DefaultCsrfProvider.php

@@ -30,6 +30,9 @@ class DefaultCsrfProvider implements CsrfProviderInterface
     /**
      * Initializes the provider with a secret value
      *
+     * A recommended value for the secret is a generated value with at least
+     * 32 characters and mixed letters, digits and special characters.
+     *
      * @param string $secret  A secret value included in the CSRF token
      */
     public function __construct($secret)

+ 3 - 0
src/Symfony/Component/Form/CsrfProvider/SessionCsrfProvider.php

@@ -31,6 +31,9 @@ class SessionCsrfProvider extends DefaultCsrfProvider
     /**
      * Initializes the provider with a Session object and a secret value
      *
+     * A recommended value for the secret is a generated value with at least
+     * 32 characters and mixed letters, digits and special characters.
+     *
      * @param Session $session  The user session
      * @param string $secret    A secret value included in the CSRF token
      */

+ 39 - 0
src/Symfony/Component/Form/FormFactory.php

@@ -13,6 +13,8 @@ namespace Symfony\Component\Form;
 
 use Symfony\Component\Form\FieldFactory\FieldFactoryInterface;
 use Symfony\Component\Form\CsrfProvider\CsrfProviderInterface;
+use Symfony\Component\Form\CsrfProvider\DefaultCsrfProvider;
+use Symfony\Component\Form\Exception\FormException;
 use Symfony\Component\Validator\ValidatorInterface;
 
 /**
@@ -54,6 +56,43 @@ class FormFactory implements FormContextInterface
      */
     protected $defaultContext;
 
+    /**
+     * Builds a form factory with default values
+     *
+     * By default, CSRF protection is enabled. In this case you have to provide
+     * a CSRF secret in the second parameter of this method. A recommended
+     * value is a generated value with at least 32 characters and mixed
+     * letters, digits and special characters.
+     *
+     * If you don't want to use CSRF protection, you can leave the CSRF secret
+     * empty and set the third parameter to false.
+     *
+     * @param ValidatorInterface $validator  The validator for validating
+     *                                       forms
+     * @param string $csrfSecret             The secret to be used for
+     *                                       generating CSRF tokens
+     * @param boolean $csrfProtection        Whether forms should be CSRF
+     *                                       protected
+     * @throws FormException                 When CSRF protection is enabled,
+     *                                       but no CSRF secret is passed
+     */
+    public static function buildDefault(ValidatorInterface $validator, $csrfSecret = null, $csrfProtection = true)
+    {
+        $context = new FormContext();
+        $context->csrfProtection($csrfProtection);
+        $context->validator($validator);
+
+        if ($csrfProtection) {
+            if (empty($csrfSecret)) {
+                throw new FormException('Please provide a CSRF secret when CSRF protection is enabled');
+            }
+
+            $context->csrfProvider(new DefaultCsrfProvider($csrfSecret));
+        }
+
+        return new static($context);
+    }
+
     /**
      * Sets the given context as default context
      *

+ 60 - 0
tests/Symfony/Tests/Component/Form/FormFactoryTest.php

@@ -0,0 +1,60 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Tests\Component\Form;
+
+require_once __DIR__ . '/Fixtures/Author.php';
+require_once __DIR__ . '/Fixtures/TestField.php';
+
+use Symfony\Component\Form\FormFactory;
+use Symfony\Component\Form\FormContext;
+use Symfony\Component\Form\CsrfProvider\DefaultCsrfProvider;
+
+class FormFactoryTest extends \PHPUnit_Framework_TestCase
+{
+    protected $validator;
+
+    protected function setUp()
+    {
+        $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface');
+    }
+
+    public function testBuildDefaultWithCsrfProtection()
+    {
+        $factory = FormFactory::buildDefault($this->validator, 'secret');
+
+        $context = new FormContext();
+        $context->validator($this->validator);
+        $context->csrfProtection(true);
+        $context->csrfProvider(new DefaultCsrfProvider('secret'));
+
+        $this->assertEquals(new FormFactory($context), $factory);
+    }
+
+    public function testBuildDefaultWithoutCsrfProtection()
+    {
+        $factory = FormFactory::buildDefault($this->validator, null, false);
+
+        $context = new FormContext();
+        $context->validator($this->validator);
+        $context->csrfProtection(false);
+
+        $this->assertEquals(new FormFactory($context), $factory);
+    }
+
+    /**
+     * @expectedException Symfony\Component\Form\Exception\FormException
+     */
+    public function testBuildDefaultWithoutCsrfSecretThrowsException()
+    {
+        FormFactory::buildDefault($this->validator, null, true);
+    }
+}