CakePHP ajax CSRF令牌不匹配

时间:2015-11-25 14:13:11

标签: ajax cakephp-3.0 csrf-protection

我在AppController

中使用Csrf组件加载进行ajax请求

但是我收到错误{"message":"CSRF token mismatch.","url":"\/module_slides\/loadDeck.json","code":403}

这是请求标题

POST /module_slides/loadDeck.json HTTP/1.1
Host: www.hotelieracademy.com
Connection: keep-alive
Content-Length: 18
Origin: https://www.hotelieracademy.com
X-XSRF-TOKEN: 3d3901b1de9c5182dce2877c9e1d9db36cdf46a6
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Referer: https://www.hotelieracademy.com/courses_employees/player/70
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: csrfToken=3d3901b1de9c5182dce2877c9e1d9db36cdf46a6; CAKEPHP=3n6lpi94hrdgsg8mv4fsnp1m30; _ga=GA1.2.2010364689.1424741587

我的ajax代码

$.ajax({
            url: '/module_slides/loadDeck.json',
            type: 'POST',
            headers: { 'X-XSRF-TOKEN' : this.csrfToken },
            beforeSend: function (xhr) {
                xhr.setRequestHeader('X-CSRF-Token', this.csrfToken);
            },
            dataType: 'json',
            data: {

我已将beforeSend:作为另一篇文章的建议而离开,但似乎没有更改标题,因此我添加了headers:

我使用隐藏输入来获取在我的js代码中使用的CsfR标记

<input id="csrfToken" type="hidden" value="<?= $this->request->params['_csrfToken'] ?>">

2 个答案:

答案 0 :(得分:4)

我遇到了同样的问题。 也许,这是将“_csrfToken”:“xxxxxxx”添加到数据{}的答案。

$.ajax({
        url: '/module_slides/loadDeck.json',
        type: 'POST',
        headers: { 'X-XSRF-TOKEN' : this.csrfToken },
        beforeSend: function (xhr) {
            xhr.setRequestHeader('X-CSRF-Token', this.csrfToken);
        },
        dataType: 'json',
        data: {
           "_csrfToken":"3d3901b1de9c5182dce2877c9e1d9db36cdf46a6"
        }

这是我的博客。但它仅限日语。 http://www.tsuji75.com/?p=62

答案 1 :(得分:0)

这是我的解决方法。
对于CSRF令牌,我正在创建一个空的cakephp表单,它提供了CSRF令牌。 另外,我没有解锁任何动作。相反,我会解锁字段。

参考:https://book.cakephp.org/3.0/en/controllers/components/security.html

这是我的工作示例。

场景:由于cakephp 3 CSRF令牌不匹配问题,Ajax调用添加事件失败。

解决方案:

  1. 我在视图中创建了一个空表单,因此它可以为表单提供CSRF令牌,然后在ajax之前附加所需的输入字段。在表单本身中,我解锁了隐藏字段。这样我就不会打扰CSRF组件。 在VIEW中

    <?= $this->Form->create(false, [
        'id' => "ajaxForm",
                            'url' => ['controller' => 'XYZ', 'action' => 'add'],
                            'class'=> "addUpdateDeleteEventForm"
                            ] );
                            $eventdata = [];
                            ?>
                                <?= $this->Form->unlockField('id'); ?>
                                <?= $this->Form->unlockField('start'); ?>
                                <?= $this->Form->unlockField('end'); ?>
                                <?= $this->Form->unlockField('title'); ?>
                            <?= $this->Form->button('Submit Form', ['type' => 'submit']);?>
    
                           <?= $this->Form->end(); ?>
    
  2. Ajax:

            var id = $("<input>")
            .attr("type", "hidden")
            .attr("name", "id").val(id);
        var titleField = $("<input>")
            .attr("type", "hidden")
            .attr("name", "title").val(title);
        var startTime = $("<input>")
            .attr("type", "hidden")
            .attr("name", "start").val(start);
        var endTime = $("<input>")
            .attr("type", "hidden")
            .attr("name", "end").val(end);
        $('#ajaxForm').append(id);
        $('#ajaxForm').append(titleField);
        $('#ajaxForm').append(startTime);
        $('#ajaxForm').append(endTime);
    
    
        var ajaxdata = $("#ajaxForm").serializeArray();
    
        $.ajax({
            url:$("#ajaxForm").attr("action"),
            type:"POST",
            data:ajaxdata,
            dataType: "json",
            success:function(response)
            {
                toastr.success(response.message, response.title);
                calendar.fullCalendar("removeEvents");
                calendar.fullCalendar("refetchEvents");
            },
            error: function(response)
            {
                toastr.error(response.message, response.title);
            }
        });
    

希望这会有所帮助。