5

我正在尝试将一些数据传递到我的控制器中,但出现 500 错误。经过一番研究,我发现这是由于没有发送 CSRF 令牌造成的。

看来我需要将其与数据一起包括在内:<?php echo $this->security->get_csrf_token_name(); ?>:"<?php echo $this->security->get_csrf_hash(); ?>"

我的 JS 很弱,所以我对如何更改它以包含上述内容有点困惑。

<script type="text/javascript"> 
$(document).ready(function() {
    $("#order").sortable({
        update : function (event, ui) {
            order = $('#order').sortable('serialize');
            $.ajax({
                url: "<?=base_url().'admin/category/update_order'?>",
                type: "POST",
                data: order,
                success: function(response){
                    console.log(response);
                }
            });
        }
    });
}
);
</script>
4

6 回答 6

4

令牌需要在 的data参数中传递$.ajax

这应该可行,但请参阅下面的注释。

order['<?php echo $this->security->get_csrf_token_name(); ?>'] = '<?php echo $this->security->get_csrf_hash(); ?>';

但是,这里有一些不好的做法。主要是您不应该在您的 javascript 中使用 PHP,因为这会阻止您将 javascript 作为单独的文件访问(这很好,因为浏览器会缓存它以使您的页面加载更快并消耗更少的带宽)。

最好像这样将令牌存储在您的订单<form>html 中。

<input type="hidden" name="<?php echo $this->security->get_csrf_token_name(); ?>" value="<?php echo $this->security->get_csrf_hash(); ?>" />

然后它将与您的其余表单数据一起序列化。

您还可以将 URL 存储在表单的操作属性中。这将帮助您的脚本优雅地降级,并将 URL 保留在一个位置而不是 2 个位置。

<form id="order" method="post" action="<?=base_url()?>admin/category/update_order">

$.ajax调用中,url: $('#order').attr('action'),假设 #order 是实际的表单 ID,请使用类似的内容。

于 2012-06-29T22:06:34.083 回答
2

CI 将 csrf 存储在 cookie 中,您可以从那里获取它:

var csrf = $.cookie('csrf_cookie_name');

这种方法的缺点是 jQuery 本身不提供 cookie 访问。所以你需要一个jquery 插件

于 2012-06-30T23:53:22.730 回答
1

您是对的,只需将 CSRF 令牌添加到您的帖子数据中即可。您可以使用 jQuery 的 $.extend 函数将您已经创建的订单对象与 CSRF 令牌数据合并,如下所示:

$.extend(alerts, {
'<?php echo $this->security->get_csrf_token_name(); ?>' :
'<?php echo $this->security->get_csrf_hash(); ?>' });
于 2012-06-29T22:03:31.373 回答
1

Here's a different approach. Simple function in Auth.php that returns the csrf token name and hash in JSON format. Then, in our javascript, make two ajax calls, the first to grab the csrf creds and insert them into hidden form fields, the second to handle our actual form submit.

// place function in Auth.php controller

public function get_csrf()
{
    $csrf['csrf_name'] = $this->security->get_csrf_token_name();
    $csrf['csrf_token'] = $this->security->get_csrf_hash();

    echo json_encode($csrf);
}

// myFunction()

<script type="text/javascript">
function myFunction() {

    // first ajax call to grab the csrf name and token
    // from our get_csrf() function in Auth.php
    $.ajax({
        type: "GET",
        dataType: 'json',
        url: "https://<your_domain>.com/auth/get_csrf", //replace with your domain
        success: function (data) {

            // assign csrf name and token to variables
            csrf_name = data.csrf_name;
            csrf_token = data.csrf_token;

            // assign field1 and field2 field values to variables
            var form_field1 = document.getElementById('field1').value;
            var form_field2 = document.getElementById('field2').value;

            // insert csrf creds into form
            $('#csrftoken').attr('name', csrf_name);
            $('#csrftoken').val(csrf_token);

            // second ajax call -- this is our form handler
            $.ajax({
                type: "POST",
                url: "https://<your_domain>.com/<your_controller>/<your_function>", //replace with your domain/controller/function
                data: {
                    // ES6 computed property keys are great...
                    [csrf_name] : csrf_token,
                    "field1" : form_field1,
                    "field2" : form_field2
                      },
                success: function(data) {

                    // handle the return from your form submit
                    if (data == "ok") {
                        console.log("Success!");
                        $("#infoMessage").html("<p>Success</p>").fadeIn(300);

                    } else {

                        console.log("Oops!");
                        $("#infoMessage").html("<p>Oops!</p>");

                    }

                }
            });

        }
    });

}
</script>

// html

<div id="infoMessage"></div>

<form method="post" accept-charset="utf-8">

    <input type="hidden" id="csrftoken" name="" value="" />

    <label for="field1">Field 1:</label> <br />
    <input type="text" name="field1" id="field1"  />

    <label for="field2">Field 2:</label> <br />
    <input type="text" name="field2" id="field2"  />

    <input type="button" name="submit" value="SUBMIT" onclick="myFunction()" />

</form>
于 2017-04-16T04:38:20.067 回答
0

另一种解决方案是使用 .serialize():

$.post("user/save", $('#frmUser').serialize(),function(html){
        $("#results").html(html);
});

这将找到存储 CSRF 数据的隐藏字段。

于 2012-07-02T18:54:13.610 回答
0

我扩展form_helperMY_form_helper.php向我自己的表单生成代码提供 csrf 令牌 - 你可以使用类似的东西:

    function secure_form() {
        $CI =& get_instance();
        return '<input type="hidden" name='.$CI->security->get_csrf_token_name().' value='.$CI->security->get_csrf_hash().'>';
    }
于 2012-06-30T22:53:11.560 回答