Защита CSRF, ошибка при включении, ошибка при выключении?

#symfony #symfony-forms #symfony-security

Вопрос:

Я работаю над веб-приложением и сталкиваюсь с проблемой, когда я отправляю свою форму, в ней отображается ошибка защиты CSRF, это не будет проблемой, так как она мне не нужна в этой форме(не содержит конфиденциальных данных, и я реализовал, что только пользователи с некоторыми привилегиями(ролями) могут получить доступ к этой странице).

Моя проблема в том, что когда я использую 'csrf_protection' => false, параметры типа формы, я получаю следующую ошибку: отсутствуют некоторые обязательные параметры («идентификатор») для создания URL-адреса для маршрута «мой маршрут».

Я бы не возражал, чтобы защита CSRF была включена, но тогда она показывает эту уродливую ошибку в моей веточке:

Токен CSRF недействителен, попробуйте отправить форму aigan

Да, я знаю, что приведенный выше блок не совсем то, что в нем написано, но я перевел его с моего родного языка.

Кто-нибудь знает быстрое решение этой проблемы?

Функция Контроллера

     /**
 * @Route("/{id}/edit", name="score_edit", methods={"GET","POST"})
 */
public function edit(Request $request, Duel $duel, DuelRepository $duelRepository): Response
{

    $form = $this->createForm(ScoreType::class, $duel);
    $form->handleRequest($request);

    if ($form->isSubmitted() amp;amp; $form->isValid()) {
        $this->getDoctrine()->getManager()->flush();

        return $this->redirectToRoute('score_edit');
    }

    return $this->render('score/edit.html.twig', [
        'duels' => $duelRepository->findAll(),
        'duel' => $duel,
        'form' => $form->createView(),
    ]);
}
 

Тип формы

     class ScoreType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('puntenP1', TextareaType::class, [
                'label' => 'Punten',
                'attr' => array('style' => 'height: 25px;')
            ])
            ->add('eerstenP1', TextareaType::class, [
                'label' => 'Eersten',
                'attr' => array('style' => 'height: 25px;')
            ])
            ->add('puntenP2', TextareaType::class, [
                'label' => 'Punten',
                'attr' => array('style' => 'height: 25px;')
            ])
            ->add('eerstenP2', TextareaType::class, [
                'label' => 'Eersten',
                'attr' => array('style' => 'height: 25px;')
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Duel::class,
            //csrf protection not needed for "scores"
            //'csrf_protection' => false,
        ]);
    }
}
 

Напильник из веточек

    {{ form_start(form) }}

<div class="row">
    <div class="col">
        <p><b>Partuur 1</b></p>
        {{ duel.team1 }}
    </div>
</div>

<div class="row">
    <div class="col">
        {{ form_row(form.puntenP1) }}
        <p>Huidig: {{ duel.puntenP1 }}</p>
    </div>
</div>

<div class="row">
    <div class="col">
        {{ form_row(form.eerstenP1) }}
       <p>Huidig: {{ duel.eerstenP1 }}</p>
    </div>
</div>
<hr>
<div class="row">
    <div class="col">
        <p><b>Partuur 2</b></p>
        {{ duel.team2 }}
    </div>
</div>

<div class="row">
    <div class="col">
        {{ form_row(form.puntenP2) }}
        <p>Huidig: {{ duel.puntenP2 }}</p>
    </div>
</div>

<div class="row">
    <div class="col">
        {{ form_row(form.eerstenP2) }}
        <p>Huidig: {{ duel.eerstenP2 }}</p>
    </div>
</div>
    {{ form_widget(form) }}

    <button class="btn btn-success" style="margin-top: 10px">{{ button_label|default('Save') }}</button>

{{ form_end(form) }}
 

Комментарии:

1. Всегда включайте достаточное количество кода, чтобы понять, что происходит на практике (например, объявление контроллера и формы здесь и, возможно, шаблон ветки). В первом говорится, что вы создаете маршрут без id компонента, что не похоже на CSRF, во втором вы, возможно, не включаете (веточку?) {{ csrf_token('form') }} позвоните по форме. Прошло какое-то время, так что я точно не помню. Кроме того, CSRF работает с зарегистрированными пользователями, поскольку он использует их сеанс для отправки запроса, поэтому отключение CSRF, когда кто-то вошел в систему, бессмысленно, и чувствительность данных также не всегда имеет значение.

2. Спасибо за ваш комментарий, я обновил свой пост

3. Попробуйте {{ csrf_token('form') }} между {{ form_widget(form) }} и {{ form_end(form) }} и не отключайте его. Вы также можете заглянуть в исходный код браузера, чтобы узнать, включено ли поле ввода токена.

4. Добавление этого предоставляет токен csrf, поэтому я не понимаю, почему он говорит, что он недействителен

5. Вы понимаете, что ваша ошибка «отсутствует идентификатор» не связана с csrf? Вернитесь и выключите csrf, затем следуйте ответу, чтобы добавить отсутствующий идентификатор в свой редирект. Вы должны получить чистую публикацию и перенаправление. Затем сделайте шаг назад и, возможно, полностью создайте другую форму и выясните, почему ваша конфигурация csrf нарушена. Решайте по одной проблеме за раз.

Ответ №1:

Это код, который вызывает проблему:

 return $this->redirectToRoute('score_edit');
 

Вы перенаправляете пользователя на этот маршрут без параметров, но маршрут имеет требуемые параметры:

 @Route("/{id}/edit", name="score_edit", methods={"GET","POST"})
 

Вы должны добавить необходимый параметр в свой маршрут:

 return $this->redirectToRoute('score_edit', [
    'id' => $duel->getId(),
]);
 

Комментарии:

1. Странно видеть, что вопрос с особым названием, связанным с CSRF, решается с помощью ответа, специфичного для маршрутизации. Вы тоже знаете, как решить проблему CSRF?