9

创建功能测试以测试在 Symfony 中启用 CSRF 保护的表单的最佳方法是什么?

目前我必须在每个表单提交之前添加以下代码:

  $form = new sfGuardFormSignin();
  $token = $form->getCSRFToken();
  $token_name = $form->getCSRFFieldName();

然后我添加 $token 和 $token_name 来形成这样的参数:

call('/login', 'POST', array (
    'signin' => 
    array (
      'username' => $username,
      'password' => $password,
      $token_name => $token,
    )))

文档中建议的选项:

'_with_csrf' => true,

根本不起作用。

有没有更简单的方法可以避免向手动测试的每个表单添加令牌?或者有没有办法在运行测试时关闭 csrf 检查?

当您必须测试 1-2 个表单时,我上面描述的方式是可以的,但如果项目包含数十个独特的表单,它就会变得很痛苦。

4

5 回答 5

4

当然,如果直接调用 url,就不能使用 _with_csrf 选项。您必须从表单页面通过,单击提交按钮。像这样:

click('signin', array('signin' => array('username' => $username, 'password' => $password), array('_with_csrf' => true)))

字符串“signin”必须适应您的表单。您还可以使用更独立于标签的字符串,例如 'form#myform input[type="submit"]' 而不是 'signin',从而调整表单的 id。

正如已经建议的那样,您可以禁用 CSRF 进行登录,这对于修改数据的表单非常有用。

于 2010-06-17T10:04:48.653 回答
3

我个人不会广泛使用功能测试(可能对我自己不利),但您始终可以在表单类中关闭 CSRF 保护以进行测试。

public function configure ()

  $this->disableLocalCSRFProtection();
于 2010-02-20T13:16:16.620 回答
2

您可以通过添加额外的编译器通道来禁用所有表单的 csrf 保护:

class CsrfProtectionCompilerPass implements CompilerPassInterface
{
    /**
     * {@inheritdoc}
     */
    public function process(ContainerBuilder $container)
    {
        $env = $container->getParameter('kernel.environment');
        if ($env == 'test') {
            $container->setParameter('form.type_extension.csrf.enabled', false);
        }
    }
}

或者您可以通过添加到配置来完全禁用表单扩展:

framework:
    csrf_protection: false

顺便说一句,仅当您没有明确设置表单选项时,最后一个解决方案才有效csrf_protection

于 2016-03-02T12:03:30.003 回答
0

您应该通过显示包含表单的页面来获取 CSRF 令牌。

$browser->get('/login');
$dom = new DOMDocument('1.0', $browser->getResponse()->getCharset());
$dom->loadHTML($browser->getResponse()->getContent());
$domCssSelector = new sfDomCssSelector($dom);
$token = $domCssSelector->matchSingle('input[name="_csrf_token"]')->getNode()->getAttribute('value');
于 2012-10-29T10:06:28.333 回答
0

我会关闭 CSRF 以进行测试环境。

于 2010-03-01T16:23:04.707 回答