在 Symfony 中防止 "Overposting Forms"
Protect against "Overposting Forms" within Symfony
过度post表单是操纵数据/入侵网站的一种常见方式。
该可能的安全问题的原因是 Form/Model Binder,它会自动将 Form 绑定到对象。在 ASP.NET 内,我知道如何防范此类攻击。
我们有一个用户模型,包含以下字段:ID、名字、姓氏、密码。我希望用户能够更改他的名字和姓氏。
正如我们所知,这发生在 Symfony(和 ASP.NET MVC)中,带有一个 Form/Model Binder,它接受表单的 "names" 并将这些值映射到相应的对象字段。
ASP.NET 中的解决方案,在每个 "Post-Controller" 上使用 [Bind] 表达式:
public async Task<ActionResult> Create([Bind(Include="FirstName,Lastname")] Employee employee)
如何在 Symfony 应用程序中防止这种攻击?如何告诉 Model/Form 活页夹,哪些 post 数据应该只被接受/预期?
@编辑:
这个问题旨在了解在将 FormType 用于多个用例时如何解决此类问题,例如用于创建和编辑员工。我知道一般来说,Symfony 表单组件已经检查是否有任何额外的字段。
如果您对 symfony 表单使用食谱(阅读:正常)方法,那么您已经拥有该保护以及 CSRF 保护。
如果您向请求添加额外的字段,您将收到以下错误:
This form should not contain extra fields
示例表格:
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title');
//Class Foo also has a text attribute
}
}
您将在控制器中使用上述 class 创建编辑或创建表单,并且只能修改添加到构建器的字段。这样 Foo::$text 就不能使用表单修改了。
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['type'] === 'edit') {
$builder->add('editMe');
//More edit me fields
}
$builder->add('createMe');
//more create me fields
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setRequired(array(
'type'
));
$resolver->setDefaults(array(
'type' => 'create'
));
}
//For consistency
public function getName()
{
return 'foo';
}
}
不需要额外的事件,因为这会有点矫枉过正。
控制器:
public function createFooAction(Request $request)
{
$form = $this->createForm(new FooType(), new Foo());
$form->handleRequest($request);
if ($form->isValid() && $form->submitted()) {
//flush form
}
return $this->render("AppBundle:Foo:create.html.twig", array(
'form' => $form
));
}
public function editFooAction(Request $request, $id)
{
$foo = ... //find($id)
$form = $this->createForm(new FooType(), $foo, array(
'type' => 'edit'
));
$form->handleRequest($request);
if ($form->isValid() && $form->submitted()) {
//flush form
}
return $this->render("AppBundle:Foo:edit.html.twig", array(
'form' => $form
));
}
过度post表单是操纵数据/入侵网站的一种常见方式。 该可能的安全问题的原因是 Form/Model Binder,它会自动将 Form 绑定到对象。在 ASP.NET 内,我知道如何防范此类攻击。
我们有一个用户模型,包含以下字段:ID、名字、姓氏、密码。我希望用户能够更改他的名字和姓氏。 正如我们所知,这发生在 Symfony(和 ASP.NET MVC)中,带有一个 Form/Model Binder,它接受表单的 "names" 并将这些值映射到相应的对象字段。
ASP.NET 中的解决方案,在每个 "Post-Controller" 上使用 [Bind] 表达式:
public async Task<ActionResult> Create([Bind(Include="FirstName,Lastname")] Employee employee)
如何在 Symfony 应用程序中防止这种攻击?如何告诉 Model/Form 活页夹,哪些 post 数据应该只被接受/预期?
@编辑: 这个问题旨在了解在将 FormType 用于多个用例时如何解决此类问题,例如用于创建和编辑员工。我知道一般来说,Symfony 表单组件已经检查是否有任何额外的字段。
如果您对 symfony 表单使用食谱(阅读:正常)方法,那么您已经拥有该保护以及 CSRF 保护。
如果您向请求添加额外的字段,您将收到以下错误:
This form should not contain extra fields
示例表格:
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('title');
//Class Foo also has a text attribute
}
}
您将在控制器中使用上述 class 创建编辑或创建表单,并且只能修改添加到构建器的字段。这样 Foo::$text 就不能使用表单修改了。
class FooType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($options['type'] === 'edit') {
$builder->add('editMe');
//More edit me fields
}
$builder->add('createMe');
//more create me fields
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setRequired(array(
'type'
));
$resolver->setDefaults(array(
'type' => 'create'
));
}
//For consistency
public function getName()
{
return 'foo';
}
}
不需要额外的事件,因为这会有点矫枉过正。
控制器:
public function createFooAction(Request $request)
{
$form = $this->createForm(new FooType(), new Foo());
$form->handleRequest($request);
if ($form->isValid() && $form->submitted()) {
//flush form
}
return $this->render("AppBundle:Foo:create.html.twig", array(
'form' => $form
));
}
public function editFooAction(Request $request, $id)
{
$foo = ... //find($id)
$form = $this->createForm(new FooType(), $foo, array(
'type' => 'edit'
));
$form->handleRequest($request);
if ($form->isValid() && $form->submitted()) {
//flush form
}
return $this->render("AppBundle:Foo:edit.html.twig", array(
'form' => $form
));
}