可以将Symfony2表单构建器用于登录表单吗?

时间:2015-03-01 01:37:22

标签: symfony login formbuilder

我花了最后几个小时试图获取使用Symfony表单构建器构建的登录表单。

据我所知,问题是表单构建器创建了formName [fieldName]形式的字段名称(例如,login [_username]),安全组件查找“flat”字段名称(例如,_username) )。这导致提交时CSRF失败。

我一直无法找到任何方法来强制表单生成器生成平面字段名称。

有没有人知道使用表单构建器构建登录表单的方法? 它甚至可能吗?

感谢。

------------更新以回应Cerad的回答-------------------

CERAD。感谢您的回复和链接。

我已将security.yml更新为:

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            pattern: ^/
            provider:
            form_login:
                check_path:                     userLoginCheck
                login_path:                     userLogin
                always_use_default_target_path: true
                default_target_path:            /
                username_parameter:             login[email]
                password_parameter:             login[password]
                csrf_parameter:                 login[_token]
                intention:                      authenticate
                csrf_provider:                  form.csrf_provider
            logout:         true
            anonymous:      true
            switch_user:    { role: ROLE_SUPER_ADMIN }

我渲染的形式与你的例子略有不同。
我正在使用表单类型并在我的控制器中调用$ this-> createForm() 渲染的表单如下所示:

<form name="login"
      method="post"
      action="/user/loginCheck"
      class="dplhUser"
      novalidate="novalidate">
  <div id="login">
    <div class="formRow">
      <label for="login_email"
             class="required">Email:</label>
      <input type="text"
             id="login_email"
             name="login[email]"
             required="required"/>
    </div>
    <div class="formRow">
      <label for="login_password"
             class="required">Password:</label>
      <input type="password"
             id="login_password"
             name="login[password]"
             required="required"/>
    </div>
    <input type="hidden"
           id="login__token"
           name="login[_token]"
           value="ij3CcnLiHzeLrNUDnxXtdExcPvGkgusIEriYmnZmgy8"/></div>
  <label for="submit"></label>
  <input type="submit"
         name="submit"
         Value="Login"/>
</form>

名称属性与security.yml中现在的名称属性相匹配 我清除了缓存并删除了会话cookie。仍然遇到CSRF失败。

表格构造:

class LoginType extends AbstractType
{
  public function buildForm( FormBuilderInterface $builder, array $options )
  {
    $builder
      ->add( 'email', null, ['mapped' => false] )
      ->add( 'password', 'password', ['mapped' => false] );
  }
  public function getName()
  {
    return 'login';
  }
  public function setDefaultOptions( OptionsResolverInterface $resolver )
  {
    $resolver->setDefaults( ['intention' => 'authentication'] );
  }
}

2 个答案:

答案 0 :(得分:1)

我认为你很接近,但不是试图更改表单字段名称,而是更改安全系统所期望的名称。大部分内容都记录在参考部分中,但确实需要花费一些时间来完成它们。

http://symfony.com/doc/current/reference/configuration/security.html

        # security.yml
        form_login:
            provider:            cerad_tourn_account_user_provider
            login_path:          cerad_tourn_account_user_login
            check_path:          cerad_tourn_account_user_login_check
            default_target_path: cerad_tourn_home

            # This matches your form element names
            username_parameter:  cerad_tourn_account_user_login[username]
            password_parameter:  cerad_tourn_account_user_login[password]
            csrf_parameter:      cerad_tourn_account_user_login[_token]
            csrf_provider:       form.csrf_provider
            intention:           authenticate

protected function createFormForModel($model)
{        
    /* ======================================================
     * Start building
     */
    $formOptions = array(
        'cascade_validation' => true,
        'intention' => 'authenticate', // Matches security.yml
        'csrf_protection' => true,
    );
    $constraintOptions = array();

    // The name here matches your security file
    $builder = $this->get('form.factory')->createNamed(
        'cerad_tourn_account_user_login',
        'form',$model,$formOptions);

    $builder->add('username','text', array(
        'required' => true,
        'label'    => 'Email',
        'trim'     => true,
        'constraints' => array(
            new UsernameOrEmailExistsConstraint($constraintOptions),
        ),
        'attr' => array('size' => 30),
     ));
     $builder->add('password','password', array(
        'required' => true,
        'label'    => 'Password',
        'trim'     => true,
        'constraints' => array(
            new NotBlankConstraint($constraintOptions),
        ),
        'attr' => array('size' => 30),
    ));
    $builder->add('remember_me','checkbox',  array('label' => 'Remember Me'));

    // Actually a form
    return $builder;
}

模板没什么特别之处,form_rest(form)会输出csrf _token。

答案 1 :(得分:1)

这项工作缺失的部分,上面没有提到:

这是您必须输入的控制器和信息:

public function loginAction()
{
    $authenticationUtils = $this->get('security.authentication_utils');

    $form = $this->createForm(new LoginType(), array(), array(
        'action' => $this->generateUrl('login_check')));
    return $this->render('AppBundle:Security:login.html.twig', array(
        'last_username' => $authenticationUtils->getLastUsername(),
        'error'         => $authenticationUtils->getLastAuthenticationError(),
        'form' => $form->createView()
    ));
}

现在,通过这个,您可以使用CreateForm()构建登录! : - )