Symfony 3,带有fetch API的“ajax请求”和CSRF

时间:2016-09-10 09:44:05

标签: ajax symfony

在twig中,我生成一个csrf标记({{ csrf_token('my_intention') }})。

在Javascript中,我用ajax调用一个控制器,实际上用Fetch API(也尝试了Ajax xmlHttpRequest),POST请求。包含请求中传递的令牌的参数名称是'token = abcdef ...'。

AJAX:

    var httpRequest = new XMLHttpRequest();
    httpRequest.onreadystatechange = function (data) {
        console.log(data);
    };

    httpRequest.open('POST', el.getAttribute("data-url"));
    httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    httpRequest.send(.......);

获取API:

        fetch(el.getAttribute('data-url'), {
            method: 'post',
            headers: {
                "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
            },
            body: 'token=' + encodeURIComponent(el.getAttribute('data-token'))
        }).then(data => data.text()).then(data => {...}

在名为i的控制器操作中,获取作为POST请求中的数据发送的令牌。我在控制器中检查这样的令牌:

    $token = $request->request->get('token');
    if (!$this->isCsrfTokenValid('my_intention', $token)) {
        throw new InvalidCsrfTokenException("error csrf 2");
    }

但Symfony说令牌无效。

我不确定,但我认为在会话变量中找不到令牌。在isTokenValid() $this->storage->hasToken($token->getId())中返回false。

在浏览器中,如果我直接调用网址,则可以。

在twig中我设置url来调用像这个data-url="{{ path('_check', {'id': transaction.id}) }}"这样的数据属性,然后我从javascript中读取这个数据属性并将其传递给ajax / fetch函数。

我用jQuery $ .post尝试了ajax(...并且它有效。唯一的区别是Cookie:PHPSESSID ...在请求标头中,jQuery不在我的原始代码上。

我不明白,我的代码出了什么问题?

Symfony 3.1.3

编辑:已解决:我没有在标头请求中传递凭据,因此,Symfony无法找到会话并检查令牌:

    fetch(el.getAttribute('data-url'), {
        method: 'post',
        headers: {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "X-Requested-With": "XMLHttpRequest"
        },
        body: 'token=' + el.getAttribute('data-token'),
        credentials: 'include'
    }).then(data => data.text()).then(data => {

1 个答案:

答案 0 :(得分:2)

即使您找到了问题的答案,我建议您查看此捆绑包,该捆绑包根据服务器端定义的Cookie处理令牌验证,并且您应该传递每个异步请求。 https://github.com/dunglas/DunglasAngularCsrfBundle