php - CSRF 无效,因为注册过程中有两个实体
问题描述
我有两个实体和一个表格用于注册过程。当我添加 csrf 令牌时,它可能适用于其中一个,而不适用于两者。
<form action="" method="post" class="registerForm" id="registerForm" novalidate>
<div class="form-row">
<div class="form-group col-lg-6">
<input type="text" class="form-control inner-blue-shadow" name="company[name]" id="companyName" placeholder="Име на фирма" required/>
<div class="invalid-feedback"></div>
<div class="valid-feedback"></div>
</div>
<div class="form-group col-lg-6">
<input type="text" class="form-control inner-blue-shadow" name="company[bulstat]" id="bulstat" placeholder="Булстат" required/>
<div class="invalid-feedback"></div>
<div class="valid-feedback"></div>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control inner-blue-shadow" name="user[username]" id="username" placeholder="Потребителско име" required/>
<div class="invalid-feedback"></div>
<div class="valid-feedback"></div>
</div>
<div class="form-group">
<input type="email" class="form-control inner-blue-shadow" name="user[email]" id="email" placeholder="Имейл адрес" required/>
</div>
<div class="form-group">
<input type="password" class="form-control inner-blue-shadow" name="user[password]" id="password" placeholder="Парола" required/>
<div class="invalid-feedback"></div>
<div class="valid-feedback"></div>
</div>
{{ form_row(form._token) }}
<div class="text-center"><button type="submit" id="registerButton">Create account</button></div>
</form>
输出是:“user__token”,据我所见,它会生成它,但仅影响两个实体之一的异常- 用户并且它不适用于另一个。
当我删除公司字段时,一切都像魅力一样。
表格是:
1.用户
public function buildForm(FormBuilderInterface $builder, array $options)
{
$schools = $this->schoolRepository->findAll();
$builder
->add('username', TextType::class)
->add('email', EmailType::class)
->add('password', PasswordType::class)
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'task_item'
));
}
2.公司:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', TextType::class);
$builder->add('bulstat', TextType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Company',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'task_item'
));
}
创建表单的控制器:
$company = new Company();
$companyForm = $this->createForm(CompanyType::class, $company);
$companyForm->handleRequest($request);
$user = new User();
$userForm = $this->createForm(UserType::class, $user);
$userForm->handleRequest($request);
我该如何解决?
解决方案
这基本上是一个如何将两个实体组合成一个形式的问题。还有其他问题可以解决这个问题,但有些问题有些陈旧且过时。这个问题也是一个没有利用 Symfony 所提供的优势并且比开发人员更努力地工作的例子。
具体来说,Symfony 开箱即用地处理 csrf,不需要特殊配置。你可以用它做更多的事情,但是从一个默认的工作实现开始,然后在必要时进行调整会更容易。以类似的方式,twig 具有表单的默认呈现。表单工作后,您可以使用各种样式工具使其看起来更漂亮。
首先简化您的 EntityType 类并添加 RegisterType:
class UserType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => User::class,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username', TextType::class)
->add('email', EmailType::class)
->add('password', PasswordType::class);
}
}
class CompanyType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Company::class,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class)
->add('bulstat', TextType::class);
}
}
class RegisterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user', UserType::class)
->add('company', CompanyType::class)
->add('register', SubmitType::class);
}
}
现在调整控制器代码并使用默认的表单渲染:
public function register(Request $request)
{
$user = new User();
$company = new Company();
$register = ['user' => $user, 'company' => $company];
$form = $this->createForm(RegisterType::class, $register);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
dump($user);
dump($company);
}
return $this->render('register.html.twig',['form' => $form->createView()]);
}
# register.html.twig
{% extends 'base.html.twig' %}
{% block body %}
<h1>Register</h1>
{{ form(form) }}
{% endblock %}
此时您应该有一个工作表格。然后,您可以添加验证和持久性以及使表单看起来不错。
推荐阅读
- xslt-1.0 - XSLT to CSV - 如何控制具有不同属性值的同一元素的顺序?
- c# - ASP .NET Core Web API - 使用 IFormFile 从上传控制器获取和提取 .zip 文件
- reactjs - 在 React.js 和 Antd 中使用 Less
- java - 在 Java 中使用 Jackson 解开嵌套 JSON 值的最简洁方法是什么?
- c++ - winapi 中的 glutpostredisplay() 等价物
- android - Xamarin.Forms FindViewById() 返回 null
- r - 在 R 中转换时间戳
- python - 用硒刮掉 giphy。无法检索正确的“src”属性
- python - 这应该是什么正则表达式模式?
- android - Appium:android Emulator:Mac M1:测试在终端上成功运行但不在模拟器上(android M1 Preview)