Symfony2表单生成器可以用于登录表单吗



在过去的几个小时里,我一直在尝试使用Symfony表单生成器构建登录表单。

据我所知,问题是表单生成器创建表单formName[fieldName]的字段名(例如login[_username]),而安全组件则查找"平面"字段名(如_username)。这会导致CSRF在提交时失败。

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

有人知道使用表单生成器构建登录表单的方法吗?这可能吗?

谢谢。

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

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

我已将我的安全性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'] );
  }
}

我认为您已经接近了,但您没有尝试更改表单字段名称,而是更改了安全系统所期望的名称。大部分内容都记录在参考部分中,但要把它们放在一起确实需要一些时间。

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。

上面没有提到的实现这一目标的缺失部分:

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

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()构建登录!:-)

最新更新