symfony4: токен csrf недействителен.Пожалуйста, попробуйте повторно отправить форму - PullRequest
0 голосов
/ 23 сентября 2018

Я получил эту ошибку в Symfony4 при отправке формы: The csrf token is invalid. Please try to resubmit the form.Я пытаюсь реализовать защиту CSRF, потому что я хочу, чтобы моя форма вводила стили с помощью Bootstrap.

Вот моя форма:

<?php

// src/Form/NewsType.php
namespace App\Form;

use App\Entity\News;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\OptionsResolver\OptionsResolver;

class NewsType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('image', NewsImageType::class, array('required' => false))
            ->add('content', TextareaType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => News::class,
            // enable/disable CSRF protection for this form
            'csrf_protection' => true,
            // the name of the hidden HTML field that stores the token
            'csrf_field_name' => '_token',
            // an arbitrary string used to generate the value of the token
            // using a different string for each form improves its security
            'csrf_token_id'   => 'publish-news',
        ));
    }
}

framework.yaml:

framework:
    secret: '%env(APP_SECRET)%'
    #default_locale: en
    csrf_protection: ~
    #http_method_override: true

    # uncomment this entire section to enable sessions
    session:
        # With this config, PHP's native session handling is used
        handler_id: ~

    #esi: ~
    #fragments: ~
    php_errors:
        log: true

Мой контроллер:

namespace App\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Filesystem\Filesystem;
use App\Entity\News;
use App\Form\NewsType;
use App\Form\NewsType2;

/**
 * @Route("/{_locale}/news", requirements={"_locale" = "fr|en"})
 */
class NewsController extends BackController
{
    /**
     * @Route("/", name="news")
     */
    public function index(Request $request)
    {
        $this->initialize();

        $repository = $this->getDoctrine()->getRepository(News::class);
        $nbNews = $repository->getNbNews();

        $news = new News();
        $form = $this->createForm(NewsType::class, $news)
            ->add('save', SubmitType::class, array('label' => 'Publier'));

        $form->handleRequest($request);

        if ($form->isSubmitted() AND $form->isValid()) {
            $submittedToken = $request->request->get('token');

            // 'publish-news' is the same value used in the template to generate the token
            if ($this->isCsrfTokenValid('publish-news', $submittedToken)) {
                $news->setUser($this->getUser());
                $news->setSharingUser($this->getUser());

                $image = $news->getImage();

                $em = $this->getDoctrine()->getManager();

                if ($image != NULL) {
                    $em->persist($image);
                }
                $em->persist($news);
                $em->flush();

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

        $this->addToTemplateArray(array(
            'form' => $form->createView(),
            'nb_news' => $nbNews,
            'nav' => "news",
        ));

        return $this->render('news/news.html.twig', $this->templateArray);
    }

Мой шаблон:

{# templates/blog/index.html.twig #}
{% extends 'base.html.twig' %}

{% block title %}{{ parent() }} | News{% endblock %}

{% block body %}
    {% if is_granted('IS_AUTHENTICATED_FULLY') %}
        <div class="news-form">
            {{ form_start(form) }}

            {#{{ form_label(form.content) }}#}
            {{ form_errors(form.content) }}
            {#{{ form_widget(form.content) }}#}

            {{ form_errors(form.image) }}
            {{ form_widget(form.image.image) }}

            {#Joindre <a href="javascript:void(0);">une photo</a> |
            <a href="javascript:void(0);">un album</a>#}

            <div class="form-group">
                <textarea class="form-control" id="news_content" name="news[content]" required="required"></textarea>
                <button type="submit" id="news_save" name="news[save]">Publier</button>
            </div>

            <input type="hidden" name="_token" value="{{ csrf_token('publish-news') }}" />

            {#{{ form_end(form) }}#}
        </div>
    {% else %}
        <a href="{{ path('login') }}">{{ 'action.sign_in'|trans }}</a> pour pouvoir publier.
    {% endif %}

    <h3>{{ 'advert.nombre'|transchoice(nb_news) }} du monde</h3>

    <div>
        <a id="sort-date" href="javascript:void(0);">Sort by date</a> |
        <a id="sort-sharings" href="javascript:void(0);">Sort by sharings</a> |
        <a id="sort-comments" href="javascript:void(0);">Sort by comments</a>
    </div>

    <div id="news-list" style="text-align: center;">
        <img src="{{ asset('images/ajax-loader.gif') }}"></img>
    </div>
{% endblock %}

{% block javascripts %}
    {{ parent() }}
    <script src="{{ asset('build/js/news.js') }}"></script>
    <script src="{{ asset('build/js/news_ready.js') }}"></script>
{% endblock %}

Я не хочу использовать {{ form_end(form) }}.Как решить эту проблему?

Я пытался воспроизвести How to Implement CSRF Protection документации Symfony.Но я не понимаю, почему произошла ошибка с токеном CSRF.

...