CSRF 令牌无效。请尝试重新提交表单。 Symfony 4
Posted
技术标签:
【中文标题】CSRF 令牌无效。请尝试重新提交表单。 Symfony 4【英文标题】:The CSRF token is invalid. Please try to resubmit the form. Symfony 4 【发布时间】:2020-07-27 01:18:43 【问题描述】:在我的表单中,用户必须选择一个选项,然后根据它选择用户。
每次尝试提交表单时都会出错。CSRF 令牌无效。请尝试重新提交表单。
我尝试使用 form_row(form._token) ,但它不起作用。 Symfony 告诉我 csrf 令牌的值是空的。
我的看法:
<div class="card">
<div class="card-body">
form_start(form)
form_rest(form)
<button class="btn btn-info">Envoyer</button>
form_end(form)
</div>
</div>
<script>
$(document).on('change', '#bsv_send_cultures', function ()
let $field = $(this)
let $form = $field.closest('form')
let data =
data[$field.attr('name')] = $field.val()
$.post($form.attr('action'), data).then(function (data)
let $input = $(data).find('#bsv_send_user')
$('#bsv_send_user').replaceWith( $input )
$('#bsv_send_user').append( "<input id=\"selectAll\" type=\"checkbox\"><label for='selectAll'>Sélectioner tous</label>" )
$("#selectAll").click(function()
$("input[type=checkbox]").prop('checked', $(this).prop('checked'));
);
)
)
</script>
我的表单生成器
class BsvSendType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
$builder
->add('cultures', EntityType::class, [
'class' => IndexCultures::class,
'choice_label' => 'name',
'mapped' => false,
'required' => false,
'placeholder' => 'Sélectionnez une culture',
'attr' => [
'class' => 'select2'
]
])
->add('display_at', DateType::class, [
'widget' => 'single_text',
'html5' => false,
'mapped' => false,
'required' => false,
'attr' => [
'class' => 'js-datepicker',
'autocomplete' => 'off'
],
'label' => 'Date d\'envoi',
'help' => 'Remplir uniquement en cas d\'envoi différé.'
])
;
$builder->get( 'cultures')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event)
$form = $event->getForm();
$this->addUserField( $form->getParent(), $form->getData());
);
$builder->addEventListener(
FormEvents::POST_SET_DATA,
function (FormEvent $event)
$form = $event->getForm();
$this->addUserField( $form, null );
);
/**
* @param FormInterface $form
* @param IndexCultures|null $indexCultures
*/
private function addUserField(FormInterface $form, ?IndexCultures $indexCultures)
if (is_null($indexCultures))
$form->add('user', EntityType::class, [
'class' => Users::class,
'mapped' => false,
'choices' => [],
'required' => false,
'placeholder' => 'Selectionner une culture avant de choisir un utilisateur'
]);
else
$form->add('user', EntityType::class, [
'class' => Users::class,
'choice_label' => function(Users $user)
return $user->getIdentity();
,
'query_builder' => function (UsersRepository $er) use ( $indexCultures )
return $er->createQueryBuilder('u')
->leftJoin( Exploitation::class, 'e', 'WITH', 'u.id = e.users')
->leftJoin(Ilots::class, 'i', 'WITH', 'e.id = i.exploitation')
->leftJoin(Cultures::class, 'c', 'WITH', 'i.id = c.ilot')
->leftJoin(IndexCultures::class, 'ic', 'WITH','c.name = ic.id')
->andWhere('ic.id = :indexC')
->setParameter('indexC', $indexCultures->getId());
,
'mapped' => false,
'expanded' => true,
'multiple' => true
]);
public function configureOptions(OptionsResolver $resolver)
$resolver->setDefaults([
'data_class' => BsvUsers::class,
'translation_domain' => 'forms'
]);
我的控制器
/**
* @Route("/admin/bsv/send/id", name="admin.bsv.send", methods="GET|POST")
* @param Bsv $bsv
* @param Request $request
* @return Response
* @throws \Exception
*/
public function send(Bsv $bsv, Request $request): Response
$bsvUsers = new BsvUsers();
$form = $this->createForm(BsvSendType::class, $bsvUsers);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
$data = $form->all();
$customers = $data['user']->getData();
$displayAt = $data['display_at']->getData();
//-- Init
$datetime = New \DateTime();
//-- Update BSV info
$bsv->setSendDate( $datetime );
//-- Create relation
foreach ($customers as $customer)
$relation = new BsvUsers();
$this->em->persist($relation);
$relation->setBsv($bsv);
$relation->setCustomers($customer);
$relation->setChecked(0);
if ( $displayAt !== null )
$displayAt->setTime(8,00);
$relation->setDisplayAt($displayAt);
else
$relation->setDisplayAt($datetime);
$this->em->flush();
$this->addFlash('success', 'BSV envoyé avec succès');
return $this->redirectToRoute('admin.bsv.index');
return $this->render('admin/bsv/send.html.twig', [
'bsv' => $bsv,
'form' => $form->createView()
]);
【问题讨论】:
【参考方案1】:看起来您发送的表单没有 _token
字段,请查看您的 JS:
...
let data =
data[$field.attr('name')] = $field.val()
$.post($form.attr('action'), data).then(...)
...
您的data
对象在发送到服务器之前仅包含#bsv_send_cultures
输入值,只需将#bsv_send__token
输入值添加到此对象,然后再从您的脚本发送。
【讨论】:
以上是关于CSRF 令牌无效。请尝试重新提交表单。 Symfony 4的主要内容,如果未能解决你的问题,请参考以下文章
Symfony3 中的错误“CSRF 令牌无效。请尝试重新提交表单”
直接访问登录表单时未设置会话 cookie,导致 CSRF 令牌无效
打开新的浏览器选项卡会使 Django 的 CSRF 令牌无效,从而阻止表单提交