API 休息 "The CSRF token is invalid. Please try to resubmit the form."

API Rest "The CSRF token is invalid. Please try to resubmit the form."

我希望将 FOS Rest Bundle 和 FOS User Bundle 合并到我的 API 应用程序中以注册新用户。问题是:

我该如何解决这些问题?

我的POSTBody

{
    "firstname": "xxx",
    "lastname": "xxx",
    "email":"xxxxx@xxxx.com",
    "username":"xxx",
    "plainPassword":{
        "first":"xxx",
        "second":"xxx"
    }
}

响应:

{
    "errors": [
        "The CSRF token is invalid. Please try to resubmit the form."
    ],
    "children": {
        "email": {},
        "username": {},
        "plainPassword": {
            "children": {
                "first": {},
                "second": {}
            }
        },
        "firstname": {},
        "lastname": {}
    }
}

UserType 表单

class UserType extends AbstractType
    {
        /**
         * @inheritDoc
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('firstname')
                ->add('lastname');
        }

        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'crsf_protection' => false,
                'csrf_token_id' => null,
                'data_class' => 'TM\UserBundle\Document\User'
            ]);
        }

        public function getParent()
        {
            return 'FOS\UserBundle\Form\Type\RegistrationFormType';

            // Or for Symfony < 2.8
            // return 'fos_user_registration';
        }
    }

控制器

class UserController extends FOSRestController
{
    /**
     * @Rest\Post("/register")
     * @param Request $request
     * @return null|Response
     */
    public function postUserAction(Request $request)
    {
        /** @var $formFactory FormFactory */
        $formFactory = $this->get('form.factory');
        /** @var $userManager UserManagerInterface */
        $userManager = $this->get('fos_user.user_manager');
        /** @var $dispatcher EventDispatcherInterface */
        $dispatcher = $this->get('event_dispatcher');

        $user = $userManager->createUser();
        $user->setEnabled(true);

        $event = new GetResponseUserEvent($user, $request);
        $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);

        if (null !== $event->getResponse()) {
            return $event->getResponse();
        }

        $form = $formFactory->create(UserType::class, $user);

        $form->submit($request->request->all());

        if ($form->isValid()) {
            $event = new FormEvent($form, $request);
            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

            $userManager->updateUser($user);

            if (null === $response = $event->getResponse()) {
                $url = $this->generateUrl('fos_user_registration_confirmed');
                $response = new RedirectResponse($url);
            }

            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

            $view = $this->view(array('token' => $this->get("lexik_jwt_authentication.jwt_manager")->create($user)), Response::HTTP_CREATED);

            return $this->handleView($view);
        }

        $view = $this->view($form, Response::HTTP_BAD_REQUEST);
        return $this->handleView($view);
    }
}

对于 API,您可能需要全面禁用 CSRF,特别是当您的 API 直接通过表单处理数据时(无论如何我都建议您这样做)。

您可以在这里找到一个巧妙的解决方案:

在您的特定情况下,我认为您可能需要删除 csrf_token_id,因为它可能会提交一个 null 值,尽管您告诉表单无论如何都要禁用它?

另外,如果您使用 Angular2 或任何其他 "modern" 前端框架作为消费者,您可能会 运行 陷入 PREFLIGHT 问题。 If/when 你也有解决办法:)