Symfony 3 - CSRF token is not allowed ONLY when sending using AJAX

Looking back, I could not find a solution. I get the error below ONLY when sending via Ajax. This means that I pre-submitted the usual Symfony style form without any problems.

CSRF symbol is invalid. Retry submitting the form.

What works:

  • regular form submission, i.e. without ajax
  • with Ajax, I checked that $ _POST is correctly populated, including the CSFR token, before being presented to the controller side as follows:

$ form-> send ($ request-> request-> will arrive ($ form-> GetName ('user')))

As requested, see below output

var_dump ($ request-> request-> will arrive ($ form-> GetName ('user')))

array(8) { 
["name"]=> string(9) "fafdffafa" 
["avatar"]=> string(9) "dfafffafa" 
["cityId"]=> string(1) "6" 
["phone"]=> string(14) "33434343434344" 
["email"]=> array(2) { 
      ["first"]=> string(22) "myemail@gmail.com" 
      ["second"]=> string(22) "myemail@gmail.com" } 
["plainPassword"]=> array(2) { 
      ["first"]=> string(8) "senha444" 
      ["second"]=> string(8) "senha444" } 
["blogSubs"]=> string(1) "1" 
["_token"]=> string(43) "hLhyoRxVYmJ_FWK0FqXmiiEYZMZ77fDAWvxCZMXCtxw" }

, , javascript , , .

var_dump, , .

array(9) { 
["name"]=> string(12) "dfdfdfdfafaf" 
["avatar"]=> string(13) "dfdfdfdafdafa" 
["cityId"]=> string(1) "8" 
["phone"]=> string(16) "3343434343343343" 
["email"]=> array(2) { 
    ["first"]=> string(22) "myemail@gmail.com" 
    ["second"]=> string(22) "myemail@gmail.com" }
["plainPassword"]=> array(2) { 
    ["first"]=> string(8) "senha444" 
    ["second"]=> string(8) "senha444" } 
["blogSubs"]=> string(1) "1" 
["save"]=> string(0) "" 
["_token"]=> string(43) "hLhyoRxVYmJ_FWK0FqXmiiEYZMZ77fDAWvxCZMXCtxw" }

, Symfony, js.

<button type="submit" id="user_save" name="user[save]" class="btn-default btn">Créer mon compte</button>

( $builder, )

////register.html.twig

{{ form_start(form, { 'attr': { 'id': 'signup_form' }}) }}
    <div class="contact input-group">
        {{ form_widget(form.name) }}
    </div>
    <div class="contact input-group">
        {{ form_widget(form.avatar) }}
        <span class="input-group-addon" id="info_avatar">
            <i class="fa fa-info"></i>
        </span>       
    </div>
    <div class="contact input-group">
        {{ form_widget(form.cityId) }}
    </div>
    <div class="contact input-group">
        {{ form_widget(form.phone) }}           
    </div>
    <div class="contact input-group">
        {{ form_widget(form.email) }}
    </div>
    <div class="contact input-group">
        {{ form_widget(form.plainPassword) }}
    </div>
    <div class="contact">
        {{ form_widget(form.blogSubs) }}
    </div>
    <div class="contact form-group ">
        {{ form_widget(form.save) }}
    </div>
{{ form_end(form) }} 

Javascript :

<script>
    $('body').on('submit','#signup_form',function(event) {
        event.preventDefault();
        var str = $("#signup_form").serialize();
        $.ajax({
            url: "/inscription",
            type: "POST",
            dataType:"json",
            data: str,
            success: function (data) {
                            alert(data);
            }   
        });
    });
  </script>

( getErrorMessages() SO.)

/src/UsedBundle/Controller/RegistrationController.php

namespace UsedBundle\Controller;

use UsedBundle\Form\UserType;
use UsedBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;

class RegistrationController extends Controller
{
/**
 * @Route("/inscription", name="inscription")
 */
public function registerAction(Request $request)
{
    $user = new User();
    $form = $this->createForm(UserType::class, $user);

    if ($request->isMethod('POST')) {
        var_dump($_POST);
        $form->submit($request->request->get($form->getName('user')));
        if(!$form->isValid()){ 
            $errors = $this->getErrorMessages($form);
            var_dump($errors);
        }
        if ($form->isSubmitted() && $form->isValid()) {
            $password = $this->get('security.password_encoder')
                ->encodePassword($user, $user->getPlainPassword());
            $user->setPassword($password);
            $email = $user->getEmail();
            $user->setUserKey( $email );
            $user->setUserKeyTime();
            $user->setDateReg();
            $em = $this->getDoctrine()->getManager('used');
            $em->persist($user);
            $em->flush();
            return new JsonResponse(array('message' => 'Success!'));
        }
    }else{
        return $this->render(
            'common/register.html.twig',
            array('form' => $form->createView())
        );           
    }
}

protected function getErrorMessages($form) 
{
    $errors = array();
    foreach ($form->getErrors() as $key => $error) {
        $errors[] = $error->getMessage();
    }

    foreach ($form->all() as $child) {
        if (!$child->isValid()) {
            $errors[$child->getName()] = $this->getErrorMessages($child);
        }
    }

    return $errors;
} 
}
+4
1

, . Symfony app_dev.php, csrf dev. javascript-

$.ajax({
    url: "/inscription",
    type: "POST",
    dataType:"json",
    data: str,
    success: function (data) {
                    alert(data);
    }   
});

Symfony, url /location prod, , CSRF .

, Symfony, . FOSJsRoutingBundle. CSRF dev:

# app/config/config_dev.yml
framework:
    csrf_protection: false
+1

Source: https://habr.com/ru/post/1679917/


All Articles