获取CSRF令牌测试,与QUOT; CSRF令牌无效" - 功能AJAX测试 [英] Get the CSRF token in a test, "CSRF token is invalid" - functional ajax test

查看:418
本文介绍了获取CSRF令牌测试,与QUOT; CSRF令牌无效" - 功能AJAX测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图测试在Symfony2中的 AJAX 请求。我正在写一个单元测试,抛出下面的错误在我的应用程序/日志/ test.log中

  request.CRITICAL:未捕获的PHP异常Twig_Error_Runtime:
上的字符串变量不可能访问的属性(0)
(以下简称CSRF令牌无效,请尝试重新提交表单。)
在... /供应商/枝/枝/ lib中/嫩枝/的template.php:388
 

我的code是相当直接的。

 公共职能testAjaxJsonResponse()
{
    $形式['后'] ['标题'] ='测试题;
    $形式['后'] ['内容'] ='测试内容;
    $形式['后'] ['_令牌'] = $客户 - > getContainer() - >获得(form.csrf_provider') - > generateCsrfToken();

    $客户 - >请求('POST','/路径/要/ AJAX /',$形式,阵列(),数组(
        HTTP_X请求的,随着'=> XMLHtt prequest',
    ));

    $响应= $客户 - > GETRESPONSE();
    $这个 - > assertSame(200,$客户 - > GETRESPONSE() - >的getStatus code());
    $这个 - > assertSame(应用/ JSON',$响应 - >包头中>获得(Content-Type的'));
}
 

这个问题似乎是 CSRF 标记,我可以禁用它的测试,但我真的不希望这样做,我是有工作通过2请求(第一次加载页面的形式,我们抢 _token XMLHtt prequest ) - !这显然显得相当愚蠢的和低效的。

解决方案

解决方案

我们可以生成自己的 CSRF 标记为 AJAX 与要求:

<$p$p><$c$c>$client->getContainer()->get('form.csrf_provider')->generateCsrfToken($intention);

下面的变量 $意向指的是阵列的关键在你的表单类型选项设置

添加意向

在你的表单类型您将需要添加意向键。例如:

 #AcmeBundle \表\型号\ PostType.php

/ **
 *附加​​字段(如果你想编辑),显示的数值为默认
 *
 *'csrf_protection'=&GT;真正,
 *'csrf_field_name'=&GT; _token',//这必须在你的测试赛
 *
 * @参数OptionsResolverInterface $解析
 * /
公共职能setDefaultOptions(OptionsResolverInterface $解析器)
{
    $ resolver-&GT;使用setdefaults(阵列(
        data_class'=&GT; 尖端\ AcmeBundle \实体\邮报,
        //唯一键来帮助生成的秘密令牌
        '意向'=&GT; post_type,
    ));
}
 

阅读文档

生成CSRF令牌在功能测试

现在我们有一个意向,我们可以用它在我们的单元测试,以产生一个有效的 CSRF 标记。

  / **
 *测试阿贾克斯JSON响应与CSRF令牌
 *例使用`POST`实体
 *
 * PHP的code返回`返回新JsonResponse(真,200);`
 * /
公共职能testAjaxJsonResponse()
{
    //表单域(确保它们通过验证!)
    $形式['后'] ['标题'] ='测试题;
    $形式['后'] ['内容'] ='测试内容;

    //创建我们的CSRF令牌 - 与$意向=`post_type`
    $ csrfToken = $客户 - &GT; getContainer() - &GT;获得(form.csrf_provider') - &GT; generateCsrfToken('post_type');
    $形式['后'] ['_令牌'] = $ csrfToken; //将它添加到你的`csrf_field_name`

    //模拟Ajax请求
    $客户 - &GT;请求('POST','/路径/要/ AJAX /',$形式,阵列(),数组(
        HTTP_X请求的,随着'=&GT; XMLHtt prequest',
    ));

    //测试我们得到一个有效的JSON响应
    $响应= $客户 - &GT; GETRESPONSE();
    $这个 - &GT; assertSame(200,$客户 - &GT; GETRESPONSE() - &GT;的getStatus code());
    $这个 - &GT; assertSame(应用/ JSON',$响应 - &GT;包头中&GT;获得(Content-Type的'));

    //断言内容
    $这 - &GT;的assertEquals(真,$响应 - &GT;的getContent());
    $这 - &GT; assertNotEmpty($客户端 - &GT; GETRESPONSE() - &GT;的getContent());
}
 

I'm trying to test an ajax request in Symfony2. I'm writing a unit test which is throwing the following error in my app/logs/test.log:

request.CRITICAL: Uncaught PHP Exception Twig_Error_Runtime: 
"Impossible to access an attribute ("0") on a string variable 
("The CSRF token is invalid. Please try to resubmit the form.")
in .../vendor/twig/twig/lib/Twig/Template.php:388

My code is fairly straight-forward.

public function testAjaxJsonResponse()
{
    $form['post']['title'] = 'test title';
    $form['post']['content'] = 'test content';
    $form['post']['_token'] = $client->getContainer()->get('form.csrf_provider')->generateCsrfToken();

    $client->request('POST', '/path/to/ajax/', $form, array(), array(
        'HTTP_X-Requested-With' => 'XMLHttpRequest',
    ));

    $response = $client->getResponse();
    $this->assertSame(200, $client->getResponse()->getStatusCode());
    $this->assertSame('application/json', $response->headers->get('Content-Type'));
}

The issue seems to be the CSRF token, I could disable it for the tests, but I don't really want to do that, I had it working by making 2 requests (the first one loads the page with the form, we grab the _token and make a second request using with XMLHttpRequest) - This obviously seems rather silly and inefficient!

解决方案

Solution

We can generate our own CSRF token for our ajax request with:

$client->getContainer()->get('form.csrf_provider')->generateCsrfToken($intention);

Here the variable $intention refers to an array key set in your Form Type Options.

Add the intention

In your Form Type you will need to add the intention key. e.g:

# AcmeBundle\Form\Type\PostType.php

/**
 *  Additional fields (if you want to edit them), the values shown are the default
 * 
 * 'csrf_protection' => true,
 * 'csrf_field_name' => '_token', // This must match in your test
 *
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Acme\AcmeBundle\Entity\Post',
        // a unique key to help generate the secret token
        'intention' => 'post_type',
    ));
}

Read the documentation

Generate the CSRF Token in your Functional test

Now we have that intention, we can use it in our unit test to generate a valid CSRF token.

/**
 * Test Ajax JSON Response with CSRF Token
 * Example uses a `post` entity
 *
 * The PHP code returns `return new JsonResponse(true, 200);`
 */
public function testAjaxJsonResponse()
{
    // Form fields (make sure they pass validation!)
    $form['post']['title'] = 'test title';
    $form['post']['content'] = 'test content';

    // Create our CSRF token - with $intention = `post_type`
    $csrfToken = $client->getContainer()->get('form.csrf_provider')->generateCsrfToken('post_type');
    $form['post']['_token'] = $csrfToken; // Add it to your `csrf_field_name`

    // Simulate the ajax request
    $client->request('POST', '/path/to/ajax/', $form, array(), array(
        'HTTP_X-Requested-With' => 'XMLHttpRequest',
    ));

    // Test we get a valid JSON response
    $response = $client->getResponse();
    $this->assertSame(200, $client->getResponse()->getStatusCode());
    $this->assertSame('application/json', $response->headers->get('Content-Type'));

    // Assert the content
    $this->assertEquals('true', $response->getContent());
    $this->assertNotEmpty($client->getResponse()->getContent());
}

这篇关于获取CSRF令牌测试,与QUOT; CSRF令牌无效&QUOT; - 功能AJAX测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆