[英]Symfony3 CSRF error if form contains only submit buttons
I am using Symfony v3.4
我正在使用
Symfony v3.4
I am trying to delete an item of goods from database. 我正在尝试从数据库中删除商品。 In order to do so i am using approach described here .
为了做到这一点,我使用这里描述的方法。
In short - it is possible to use two form submit buttons to decide - either: delete an item or return to list (by redirect). 简而言之-可以使用两个表单提交按钮来决定-删除项目或返回列表(通过重定向)。 After checking form validity it is possible to know which button was pressed so it suites the needs.
在检查表单有效性之后,可以知道按下了哪个按钮,从而满足了需求。 (This approach does not rely on JavaScript).
(这种方法不依赖JavaScript)。
For the purpose i created form with 2 differently named submit buttons (with no additional fields). 为此,我创建了带有2个不同名称的提交按钮的表单(没有其他字段)。 I create the form in controller and pass it to the view, it displays as expected.
我在控制器中创建表单并将其传递给视图,它按预期显示。
Problem is - when i submit form it is not valid! 问题是-我提交表格时无效! The error is:
The CSRF token is invalid. Please try to resubmit the form.
错误是:
The CSRF token is invalid. Please try to resubmit the form.
The CSRF token is invalid. Please try to resubmit the form.
Resubmitting does not change a thing, form remains not valid... 重新提交不会改变任何事情,表格仍然无效...
I thought that Symfony Forms
automatically handles CSRF token! 我认为
Symfony Forms
自动处理CSRF令牌! Does it not in this case? 在这种情况下不是吗? What am i missing?
我想念什么?
What is the best practice in this situation? 在这种情况下,最佳做法是什么?
my FormType
我的
FormType
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ReservationActionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('delete', SubmitType::class, array(
'attr' => array('class' => 'btn btn-danger'),
'label' => 'Yes, delete an item'
))
->add('return', SubmitType::class, array(
'attr' => array('class' => 'btn btn-default'),
'label' => 'No, return to list'
));
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'csrf_protection' => true,
'csrf_field_name' => '_token',
)
);
}
}
my Controller
我的
Controller
public function reservationDelete($reservation_id = 0, Request $request)
{
// get $reservation that corresponds $reservation_id from database
$form = $this->createForm(ReservationActionType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
if ($form->get('delete')->isClicked())
{
dump('replace this with item delete code');
}
else if ($form->get('return')->isClicked())
{
return $this->redirectToRoute('admin_reservations');
}
}
return $this->render('admin/reservations_use_code.html.twig',
[
'reservation_id' => $reservation_id,
'reservation' => $reservation,
'form' => $form->createView()
]
);
}
my template
part where form resides 我的表单所在的
template
部分
{% if reservation['id'] is defined %}
{{ form_start(form, {'attr': {'novalidate': 'novalidate', 'method': 'POST'}}) }}
{{ form_widget(form.delete) }}
{{ form_widget(form.return) }}
{{ form_end(form) }}
{% endif %}
Try to add the CSRF in your form directly : 尝试直接在表单中添加CSRF:
...
{{ form_row(form._token) }}
{{ form_end(form) }}
Actually, yes it can! 其实可以。
(With the small difference that rendering forms this way is specific to Twig, rather than Symfony) (区别在于这种方式形成的渲染特定于Twig,而不是Symfony)
But the way you render your form, you are actually (by mistake I guess) saying twig not to render other fields than "delete" and "return". 但是实际上,您渲染表格的方式(我猜是错误的)是说树枝不渲染 “删除”和“返回”以外的其他字段。 This is why your CSRF token is not found.
这就是为什么找不到您的CSRF令牌的原因。
Instead of rendering your fields manually, I would suggest you to use a theme ( https://symfony.com/doc/3.4/form/form_customization.html ) to customize your specific rows and fields. 我建议您使用主题( https://symfony.com/doc/3.4/form/form_customization.html )自定义特定的行和字段,而不是手动呈现字段。
Then you can just render your form in the following ways : 然后,您可以通过以下方式呈现表单:
{{ form(form) }}
To surcharge the form itself, rendering all fields automatically (including CSRF) : notice the difference between form_widget(form)
(render all fields) and form_widget(form.my_field)
(render "my_field" only) 要附加表单本身,自动渲染所有字段(包括CSRF):请注意
form_widget(form)
(渲染所有字段)和form_widget(form.my_field)
(仅渲染“ my_field”)之间的区别
{{ form_start(form, { attr: { novalidate: true }}) }}
{{ form_widget(form) }}
{{ form_end(form) }}
To surcharge a specific field without using theme (a bit heavier to write IMO), use form_rest(form)
to render all the other fields (including CSRF) 要在不使用主题的情况下附加特定字段(编写IMO会比较
form_rest(form)
),请使用form_rest(form)
渲染所有其他字段(包括CSRF)
{{ form_start(form) }}
{{ form_row(form.delete, { attr: { class: 'whatever' }}) }}
{{ form_rest(form) }}
{{ form_end(form) }}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.