Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php FOSUserBundle&;RESTAPI调用:如何使用自定义FormType?_Php_Rest_Symfony_Csrf - Fatal编程技术网

Php FOSUserBundle&;RESTAPI调用:如何使用自定义FormType?

Php FOSUserBundle&;RESTAPI调用:如何使用自定义FormType?,php,rest,symfony,csrf,Php,Rest,Symfony,Csrf,我在我的Symfony2网站上使用FOSUserBundle。现在我正在开发一个API,允许通过RESTAPI调用进行注册 我已覆盖FOSUserBundle的注册控制器: ApiRegistrationController.php: /** * @Route("/user/", defaults = { "_format" = "json" }, requirements = { "_method" = "POST" }) * */ public function registerA

我在我的Symfony2网站上使用FOSUserBundle。现在我正在开发一个API,允许通过RESTAPI调用进行注册

我已覆盖FOSUserBundle的注册控制器:

ApiRegistrationController.php:

 /**
 * @Route("/user/", defaults = { "_format" = "json" }, requirements = { "_method" = "POST" })
 * 
 */
public function registerAction(Request $request)
{
    [...]

    $form = $formFactory->createForm(new ApiRegistrationFormType(), $user);

    [...]
}
/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'BenMarten\UserBundle\Entity\User',
        'intention'  => 'registration',
        'csrf_protection' => false
    ));
}
<service id="ben_marten.rest_registration.form.type" class="BenMarten\UserBundle\Form\RestRegistrationFormType">
        <tag name="form.type" alias="fos_user_rest_registration" />
        <argument type="service" id="service_container" />
        <argument>BenMarten\UserBundle\Entity\User</argument>
    </service>
ApiRegistrationFormType.php:

 /**
 * @Route("/user/", defaults = { "_format" = "json" }, requirements = { "_method" = "POST" })
 * 
 */
public function registerAction(Request $request)
{
    [...]

    $form = $formFactory->createForm(new ApiRegistrationFormType(), $user);

    [...]
}
/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'BenMarten\UserBundle\Entity\User',
        'intention'  => 'registration',
        'csrf_protection' => false
    ));
}
<service id="ben_marten.rest_registration.form.type" class="BenMarten\UserBundle\Form\RestRegistrationFormType">
        <tag name="form.type" alias="fos_user_rest_registration" />
        <argument type="service" id="service_container" />
        <argument>BenMarten\UserBundle\Entity\User</argument>
    </service>
我得到关于错误的CSRF令牌的错误,所以我创建了自己的RegistrationFormType,以禁用CSRF-但它将被调用


我如何才能实现仅为api调用禁用CSRF令牌?

因此,经过长时间的摆弄,我让它工作起来了。我希望这能节省一些时间

我使用FOSRestBundle

我已在捆绑包中创建了自己的RestController:

RestController.php

namespace BenMarten\UserBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use FOS\RestBundle\View\View;

/**
 * Rest Controller
 */
class RestController extends Controller
{
    /**
     * Create a new resource
     *
     * @param Request $request
     * @return View view instance
     *
     */
    public function postUserAction(Request $request)
    {
        /** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
        $formFactory = $this->container->get('fos_user.registration.form.factory');
        /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
        $userManager = $this->container->get('fos_user.user_manager');
        /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
        $dispatcher = $this->container->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->createForm();
        $form->setData($user);

        $jsonData = json_decode($request->getContent(), true); // "true" to get an associative array

        if ('POST' === $request->getMethod()) {
            $form->bind($jsonData);

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

                $userManager->updateUser($user);

                $response = new Response("User created.", 201);               

                return $response;
            }
        }

        $view = View::create($form, 400);
        return $this->get('fos_rest.view_handler')->handle($view);
    }
}
namespace BenMarten\UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\DependencyInjection\Container;

class RestRegistrationFormType extends AbstractType
{
    protected $routeName;
    private $class;

    /**
     * @param string $class The User class name
     */
    public function __construct(Container $container, $class)
    {
        $request = $container->get('request');
        $this->routeName = $request->get('_route');
        $this->class = $class;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($this->routeName != "post_user")
        {
            $builder
                ->add('email', 'email', array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
                ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
                ->add('plainPassword', 'repeated', array(
                    'type' => 'password',
                    'options' => array('translation_domain' => 'FOSUserBundle'),
                    'first_options' => array('label' => 'form.password'),
                    'second_options' => array('label' => 'form.password_confirmation'),
                    'invalid_message' => 'fos_user.password.mismatch',
                ))
            ;
        }
        else
        {
            $builder
                ->add('email', 'email')
                ->add('username', null)
                ->add('plainPassword', 'password')
            ;        
        }
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        if ($this->routeName != "post_user")
        {
            $resolver->setDefaults(array(
                'data_class' => $this->class,
                'intention'  => 'registration',
            ));
        }
        else
        {
            $resolver->setDefaults(array(
                'data_class' => $this->class,
                'intention'  => 'registration',
                'csrf_protection' => false
            ));            
        }
    }

    public function getName()
    {
        return 'fos_user_rest_registration';
    }
}
resregistrationformtype.php

namespace BenMarten\UserBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use FOS\RestBundle\View\View;

/**
 * Rest Controller
 */
class RestController extends Controller
{
    /**
     * Create a new resource
     *
     * @param Request $request
     * @return View view instance
     *
     */
    public function postUserAction(Request $request)
    {
        /** @var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
        $formFactory = $this->container->get('fos_user.registration.form.factory');
        /** @var $userManager \FOS\UserBundle\Model\UserManagerInterface */
        $userManager = $this->container->get('fos_user.user_manager');
        /** @var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
        $dispatcher = $this->container->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->createForm();
        $form->setData($user);

        $jsonData = json_decode($request->getContent(), true); // "true" to get an associative array

        if ('POST' === $request->getMethod()) {
            $form->bind($jsonData);

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

                $userManager->updateUser($user);

                $response = new Response("User created.", 201);               

                return $response;
            }
        }

        $view = View::create($form, 400);
        return $this->get('fos_rest.view_handler')->handle($view);
    }
}
namespace BenMarten\UserBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\DependencyInjection\Container;

class RestRegistrationFormType extends AbstractType
{
    protected $routeName;
    private $class;

    /**
     * @param string $class The User class name
     */
    public function __construct(Container $container, $class)
    {
        $request = $container->get('request');
        $this->routeName = $request->get('_route');
        $this->class = $class;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($this->routeName != "post_user")
        {
            $builder
                ->add('email', 'email', array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
                ->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
                ->add('plainPassword', 'repeated', array(
                    'type' => 'password',
                    'options' => array('translation_domain' => 'FOSUserBundle'),
                    'first_options' => array('label' => 'form.password'),
                    'second_options' => array('label' => 'form.password_confirmation'),
                    'invalid_message' => 'fos_user.password.mismatch',
                ))
            ;
        }
        else
        {
            $builder
                ->add('email', 'email')
                ->add('username', null)
                ->add('plainPassword', 'password')
            ;        
        }
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        if ($this->routeName != "post_user")
        {
            $resolver->setDefaults(array(
                'data_class' => $this->class,
                'intention'  => 'registration',
            ));
        }
        else
        {
            $resolver->setDefaults(array(
                'data_class' => $this->class,
                'intention'  => 'registration',
                'csrf_protection' => false
            ));            
        }
    }

    public function getName()
    {
        return 'fos_user_rest_registration';
    }
}
将服务添加到Services.xml:

 /**
 * @Route("/user/", defaults = { "_format" = "json" }, requirements = { "_method" = "POST" })
 * 
 */
public function registerAction(Request $request)
{
    [...]

    $form = $formFactory->createForm(new ApiRegistrationFormType(), $user);

    [...]
}
/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'BenMarten\UserBundle\Entity\User',
        'intention'  => 'registration',
        'csrf_protection' => false
    ));
}
<service id="ben_marten.rest_registration.form.type" class="BenMarten\UserBundle\Form\RestRegistrationFormType">
        <tag name="form.type" alias="fos_user_rest_registration" />
        <argument type="service" id="service_container" />
        <argument>BenMarten\UserBundle\Entity\User</argument>
    </service>
因此,基本上我告诉FOS用户包使用我自己的注册表,并根据路线启用csrf令牌或不启用…

请更简单! 假设您同时使用
FOSRestBundle
FOSOAuthServerBundle
,您正在为已经实现的东西做大量的工作。。。我建议。。。配置文件中还有2行:)

app/config.yml

# we want to disable csrf roles for users with ROLE_API
fos_rest:
    disable_csrf_role: ROLE_API

# We want to use scope to assign this role when the user requests the token
fos_oauth_server:
        options:
            supported_scopes: user api # https://goo.gl/iE9VoI


现在怎么办? 当您使用scope api请求您的令牌时,您的用户将自动获得角色api,CSRF约束将消失


是的,在文件里:


您是如何创建自己的RegistrationFormType的。您应该重写FOSUserBundle的RegistrationFormType。是的,我的类ApiRegistrationFormType正在扩展FOSUserBundle的RegistrationFormType。但它并没有把它捡起来。。。这一行似乎不起作用:$form=$formFactory->createForm(新ApiRegistrationFormType(),$user);有什么想法吗?json对象应该看起来怎么样?我正在发送:{“用户”:{“电子邮件”:”test@test.pl“,”用户名“:”koper“,”明文密码“:”test“}}}我的表单仍然无效,没有用户对象:{”email:“test@test.pl“,”用户名“:”koper“,”明文密码“:”测试“}不起作用了好的,我必须关闭csrf,但是我仍然有违反完整性约束的情况。如果是违反完整性约束,那似乎是数据库问题。错误信息到底是什么?在这里使用表单有什么意义?只是为了验证?不确定,但如果您可以跳过这里的表单,您可以节省大量开销来拨打oauth电话,您需要用户名和密码,对吗?你一开始是怎么做到的?我想这个问题是关于注册的。一旦数据库中有用户名密码,就可以获得access\u令牌