繁体   English   中英

刷新AjaxPOST数据表上的CSRF令牌:CodeIgniter

[英]Refresh CSRF Token on AjaxPOST Datatables: CodeIgniter

我正在尝试让数据表在我的网站上运行。 但是当我点击搜索,下一页,排序时,它无法正常工作。 这是因为CSRF令牌未被重新生成。

这是我的代码:

HTML

<input type="hidden" id="hash" name="csrf_test_name" value="802daa2efaf69edb83b571d7bf7510aa">
        <table id="test-table" class="table table-hover">
            <thead>
                <tr>
                    <th>No</th>
                    <th>First Name</th>
                    <th>Last Name</th>
                    <th>Phone</th>
                    <th>Address</th>
                    <th>City</th>
                    <th>Country</th>
                </tr>
            </thead>
            <tbody>
            </tbody>

            <tfoot>
                <tr>
                    <th>No</th>
                    <th>First Name</th>
                    <th>Last Name</th>
                    <th>Phone</th>
                    <th>Address</th>
                    <th>City</th>
                    <th>Country</th>
                </tr>
            </tfoot>
        </table>

JS

<script type="text/javascript">

var table;

$(document).ready(function() {

//datatables
table = $('#test-table').DataTable({ 

    "processing": true, //Feature control the processing indicator.
    "serverSide": true, //Feature control DataTables' server-side processing mode.
    "order": [], //Initial no order.
    "ajax": {
        "url": "http://oss-dev.forexworld.us/oss/user/ajax_receiving",
        "type": "POST",
        data: {
            'csrf_test_name' : '802daa2efaf69edb83b571d7bf7510aa' 
            },
       dataSrc: function ( json ) {
           if(json.csrf_test_name !== undefined) $('meta[name=csrf_test_name]').attr("content", json.csrf_token);
           return json.data;
       }
    },
    "columnDefs": [
    { 
        "targets": [ 0 ], //first column / numbering column
        "orderable": false, //set not orderable
    },
    ],

});

});

</script>

我可以通过设置$config['csrf_regenerate'] = TRUE;来使我的数据表工作$config['csrf_regenerate'] = TRUE; 假,但我不希望这样。 我的猜测是dataSrc部分不起作用,但我不确定。

你可以在这里看到它。

任何帮助都非常感谢。 谢谢!

刷新AjaxPOST数据表上的CSRF令牌:CodeIgniter

上述陈述是自我解释的,具有明确的含义:

我们在制作AjaxPOST时必须刷新CSRF令牌

那么,我们如何在CodeIgniter中刷新CSRF令牌?什么是CodeIgniter中的平均刷新CSRF。


如果您的AJAX使用AjaxGET而不是AjaxPOST,则不会出现问题,因为CSRF仅适用于POST数据。


或者,您需要获取新的CSRF令牌和Hash并在AjaxPOST调用中返回它,然后更新html或javascript代码中的令牌和哈希设置。


或者,您可以使用config元素$ config ['csrf_exclude_uris'] = array();使特定URL免于CSRF


或者,您可以使用配置元素$ config ['csrf_expire'] = 300设置使CSRF令牌到期的长时间段; 这里定义了5分钟到期CSRF令牌,在到期时间(从第一个POST时间戳开始)之前,您可以使用在触发第一个POST时由CodeIgniter生成的旧CSRF令牌。 如果在5分钟内第一次POST后没有POST触发器,CodeIgniter将使CSRF令牌到期,之后您需要获取新的CSRF令牌。 听起来很复杂..没问题

假设您重新加载页面并且CodeIgniter将设置新的CSRF哈希,您可以使用它来发出AjaxPOST请求。 但是如果没有提出任何请求或重新加载页面,那么在5分钟之后,旧的CSRF将过期。 现在,如果再次调用AjaxPOST请求,则会收到500/403错误。 这意味着CodeIgniter会使旧的CSRF哈希到期,因为您在5分钟后使用旧的CSRF哈希发出请求,现在实际上不存在....清除:)

那么,在制作AjaxPOST时我们可以做些什么来获得新的CSRF令牌?

  • 那么,对于GET请求,不需要CSRF令牌。
  • 但对于POST是的! 如果你使用CodeIgniter CSRF Security $ config ['csrf_protection'] = TRUE,你必须用AjaxPOST发送CSRF ;

背后的逻辑是,在使用GET创建任何AjaxPOST之前获取新的CSRF哈希。 将它设置在DOM中的某个位置或附加到AjaxSetup中。

我是CodeIgniter的新手...... :(你有什么例子......?

(布尔玛!!为什么你再次打我的车......)是的! :)

这是View Html代码:

<!DOCTYPE html>
<html lang="en">
<head>

    <meta charset="utf-8">
    <meta name="<?=$this->security->get_csrf_token_name()?>" content="<?=$this->security->get_csrf_hash()?>"/>

    <title>CodeIgniter CSRF Refresh Demo</title>

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

    <script type="text/javascript">

    // Set CodeIgniter base_url in JavaScript var to use within
    var _BASE_URL_ = "<?=base_url()?>";
    var _CSRF_NAME_ = "<?=$this->security->get_csrf_token_name()?>";

    (function($) {
        /**
         * New jQuery function to set/refresh CSRF token in Body & to attach AjaxPOST
         * @param  {[type]} $ [description]
         * @return {[type]}   [description]
         */
         $.fn.CsrfAjaxSet = function(CsrfObject) {
            // getting meta object from body head section by csrf name
            var CsrfMetaObj = $('meta[name="' + _CSRF_NAME_ + '"]'),
            CsrfSecret = {};
            // if CsrfObject not set/pass in function
            if (typeof CsrfObject == 'undefined') {
                // assign meta object in CsrfObject
                CsrfObject = CsrfMetaObj;
                // get meta tag name & value
                CsrfSecret[CsrfObject.attr('name')] = CsrfObject.attr('content');
            }
            // CsrfObject pass in function
            else {
                // get Csrf Token Name from JSON
                var CsrfName = Object.keys(CsrfObject);
                // set csrf token name & hash value in object
                CsrfSecret[CsrfName[0]] = CsrfObject[CsrfName[0]];
            }
            // attach CSRF object for each AjaxPOST automatically
            $.ajaxSetup({
                data: CsrfSecret
            });
        };
        /**
         * New jQuery function to get/refresh CSRF token from CodeIgniter
         * @param  {[type]} $ [description]
         * @return {[type]}   [description]
         */
         $.fn.CsrfAjaxGet = function() {
            return $.get(_BASE_URL_ + 'Csrfdata', function(CsrfJSON) {
                $(document).CsrfAjaxSet(CsrfJSON);
            }, 'JSON');            
        };
    })(jQuery);

    // On DOM ready attach CSRF within AjaxPOST
    $(document).CsrfAjaxSet();

</script>
</head>
<body>
<button class="button">Click Me to Trigger AjaxPOST</button>
    <script type="text/javascript">
        // on DOM ready
        $(document).ready(function(){
            // my button 
            $btn = $('.button');
            // on button click
            $btn.on('click', function(e){
                // stop default event
                e.preventDefault();
                // trigger refresh csrf token
                var CSRF = $(document).CsrfAjaxGet();
                // use callback to put your AjaxPOST & Done!
                CSRF.success(function(){
                    $.ajax({
                        url: _BASE_URL_ + 'Controller/Method',
                        method: 'POST',
                        success: function(data){
                            alert('Success');
                        },
                        error: function(xhr, status, error){
                            alert(error);
                        }
                    });
                });
            });
        });
    </script>
</body>
</html>

这是控制器:

<?php 

(defined('BASEPATH') or exit('No direct script access allowed'));

/**
 * Class Csrfdata to return fresh CSRF hash value
 */
class Csrfdata extends CI_Controller
{

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Return CodeIgniter CSRF name & Hash on request
     * @return [type] [description]
     */
    public function index()
    {
        if ($this->input->get()) {
            $csrf = array();
            $csrf_name = $this->security->get_csrf_token_name();
            $csrf_hash = $this->security->get_csrf_hash();
            $csrf[$csrf_name] = $csrf_hash;
            echo json_encode($csrf);
        }

    }

}

/* End of file Csrfdata.php */
/* Location: ./application/controllers/Csrfdata.php */

希望每个人都会喜欢这个答案,任何建议,评论都非常感谢...一如既往......:D

谢谢Neeraj! 你的解决方案对我有用。

我在CodeIgniter中使用了以下代码来表示AJAX DataTable。 这是在从DataTable的AJAX调用中获取结果时触发CSRF Refresh方法。

$('#table').DataTable({ 
    "ajax": {
        "url": "<?php echo site_url(); ?>list",
        "type": "POST",
        "dataSrc": function ( json ) {
            $(document).CsrfAjaxGet();
            return json.data;
        } 
    }
});

请在脚本标记的页面中添加此行。

$(function($) {

    // this script needs to be loaded on every page where an ajax POST
    $.ajaxSetup({
        data: {
            '<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>'
        }
    });


  // now write your ajax script 

});

如果它不起作用,请告诉我

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM