/
FormTypeCsrfExtension.php
122 lines (110 loc) · 4.53 KB
/
FormTypeCsrfExtension.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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\Type;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Util\ServerParams;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class FormTypeCsrfExtension extends AbstractTypeExtension
{
private $defaultTokenManager;
private $defaultEnabled;
private $defaultFieldName;
private $translator;
private $translationDomain;
private $serverParams;
/**
* @param TranslatorInterface|null $translator
*/
public function __construct(CsrfTokenManagerInterface $defaultTokenManager, bool $defaultEnabled = true, string $defaultFieldName = '_token', $translator = null, string $translationDomain = null, ServerParams $serverParams = null)
{
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
throw new \TypeError(sprintf('Argument 4 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
}
$this->defaultTokenManager = $defaultTokenManager;
$this->defaultEnabled = $defaultEnabled;
$this->defaultFieldName = $defaultFieldName;
$this->translator = $translator;
$this->translationDomain = $translationDomain;
$this->serverParams = $serverParams;
}
/**
* Adds a CSRF field to the form when the CSRF protection is enabled.
*
* @param FormBuilderInterface $builder The form builder
* @param array $options The options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (!$options['csrf_protection']) {
return;
}
$builder
->addEventSubscriber(new CsrfValidationListener(
$options['csrf_field_name'],
$options['csrf_token_manager'],
$options['csrf_token_id'] ?: ($builder->getName() ?: \get_class($builder->getType()->getInnerType())),
$options['csrf_message'],
$this->translator,
$this->translationDomain,
$this->serverParams
))
;
}
/**
* Adds a CSRF field to the root form view.
*
* @param FormView $view The form view
* @param FormInterface $form The form
* @param array $options The options
*/
public function finishView(FormView $view, FormInterface $form, array $options)
{
if ($options['csrf_protection'] && !$view->parent && $options['compound']) {
$factory = $form->getConfig()->getFormFactory();
$tokenId = $options['csrf_token_id'] ?: ($form->getName() ?: \get_class($form->getConfig()->getType()->getInnerType()));
$data = (string) $options['csrf_token_manager']->getToken($tokenId);
$csrfForm = $factory->createNamed($options['csrf_field_name'], 'Symfony\Component\Form\Extension\Core\Type\HiddenType', $data, array(
'mapped' => false,
));
$view->children[$options['csrf_field_name']] = $csrfForm->createView($view);
}
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => $this->defaultEnabled,
'csrf_field_name' => $this->defaultFieldName,
'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.',
'csrf_token_manager' => $this->defaultTokenManager,
'csrf_token_id' => null,
));
}
/**
* {@inheritdoc}
*/
public static function getExtendedTypes(): iterable
{
return array(FormType::class);
}
}