我花了最后几个小时试图获取使用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'] );
}
}
答案 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()构建登录! : - )