2014-03-13 36 views
3

我在我的Symfony2網站上使用FOSUserBundle。現在我正在開發一個API以允許通過REST API調用進行註冊。FOSUserBundle&REST Api調用:如何使用自定義FormType?

我已經覆蓋FOSUserBundle的這個RegistrationController:

ApiRegistrationController.php:

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

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

    [...] 
} 

ApiRegistrationFormType.php:

/** 
* @param OptionsResolverInterface $resolver 
*/ 
public function setDefaultOptions(OptionsResolverInterface $resolver) 
{ 
    $resolver->setDefaults(array(
     'data_class' => 'BenMarten\UserBundle\Entity\User', 
     'intention' => 'registration', 
     'csrf_protection' => false 
    )); 
} 

我得到了錯誤的CSRF錯誤令牌,所以我創建了我自己的RegistrationFormType,禁用CSRF - 但它被稱爲...

如何才能實現禁用CSRF令牌只爲API調用?

+0

你是如何創建自己的RegistrationFormType。您應該重寫FOSUserBundle的RegistrationFormType。 –

+0

是的,我的類ApiRegistrationFormType擴展了FOSUserBundle的RegistrationFormType。但它並沒有採用它... 這行似乎不工作:$ form = $ formFactory-> createForm(new ApiRegistrationFormType(),$ user); 有什麼想法? –

回答

7

因此經過大量的時間擺弄,我得到了它的工作。我希望能夠節省一些時間。

我使用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); 
    } 
} 

RestRegistrationFormType.php

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 :

<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> 

而且在config.yml:

registration: 
    form: 
     type: fos_user_rest_registration 

所以基本上我告訴FOS用戶捆綁用自己的登記表,並根據不同的航線上啓用了CSRF令牌或不...

+0

應該看起來像json對象嗎? 我送的是:{ 「用戶」:{ 「電子郵件」: 「[email protected]」, 「用戶名」: 「科佩爾」, 「plainPassword」: 「測試」 }} 仍然和我的表單不正確 – user1483208

+0

無需用戶對象:{ 「電子郵件」: 「[email protected]」, 「用戶名」: 「科佩爾」, 「plainPassword」: 「測試」 }是不是工作壓力太大 – user1483208

+0

OK我必須關閉csrf,但仍然有違反完整性約束 – user1483208

2

更簡單請!

假設您同時使用FOSRestBundleFOSOAuthServerBundle,你做了很多工作,爲東西是已經實現的......我建議......在你的配置文件:

應用程序/配置2個額外的行.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 

Et瞧!


現在呢?

當您使用作用域API請求令牌時,您的用戶自動獲取角色ROLE_API,並且CSRF約束消失!

http://YOUR_DOMAIN/oauth/v2/token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECREY&grant_type=password&username=YOUR_USERNAME&password=YOUR_PASSWORD&scope=api


是的,它是在doc:

+2

要做一個oauth電話,你需要用戶名和密碼嗎?你如何得到這個呢?我認爲這個問題是關於註冊。一旦你在數據庫中有一個用戶名密碼,那麼你可以得到access_token – Abstract

相關問題