I'm trying to make datatables work in my website. But when I click search, next page, sorting, it's not working. This is because of the CSRF token not being regenerated.
Here's my code:
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": "",
"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>
I can make my datatable work by setting the $config['csrf_regenerate'] = TRUE;
to FALSE but I don't want that. My guess is that the dataSrc
part is not working but I'm not sure.
You can see it in action here.
Any help is highly appreciated. Thanks!
I'm trying to make datatables work in my website. But when I click search, next page, sorting, it's not working. This is because of the CSRF token not being regenerated.
Here's my code:
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>
I can make my datatable work by setting the $config['csrf_regenerate'] = TRUE;
to FALSE but I don't want that. My guess is that the dataSrc
part is not working but I'm not sure.
You can see it in action here.
Any help is highly appreciated. Thanks!
Share Improve this question asked Jun 24, 2017 at 6:51 elimariaaaelimariaaa 8764 gold badges12 silver badges37 bronze badges 1- a quick solution can be to change the ajax type to GET. Since CSRF tokens are not required on GET, everything works as it is (though need to change the PHP code to use $_GET instead of $_POST) – vishwakarma09 Commented Dec 18, 2017 at 9:07
3 Answers
Reset to default 4Refresh CSRF token on AjaxPOST Datatables: CodeIgniter
The above statement is self explanatory & has a clear meaning that:
We have to Refresh our CSRF Token before making any AjaxPOST requests
So, How we will Refresh CSRF Token in CodeIgniter & What is the meaning ff Refresh CSRF in CodeIgniter.
CSRF tokens are only required when you are making a POST requests (ajax post or normal form based post)
Alternatively, you will require to have new CSRF token & hash value before making any AjaxPOST requests. Once Ajax call is done you must update the token and hash value settings in your html or save as variable in your javascript code.
Alternatively, you can exclude the required url from CSRF (You can tell CodeIgniter "Dear CodeIgniter listen, When I will use this url, you are not allowed to check CSRF token and never asked me to attach/send CSRF token within request. Understood? Yes Master) using the config element $config['csrf_exclude_uris'] = array('controller/method', '...');
Alternatively, you can set long time period to expire CSRF token using the config element $config['csrf_expire'] = 300;. Here it is 5 minutes defined to expire the CSRF token, Before the expire time (which start with first POST timestamp) you can use old CSRF token which was generated by CodeIgniter, when you had triggered the first POST request. If no POST request triggered then after first POST request within 5 minutes, CodeIgniter will expire the existing CSRF token and after that you would need to get New CSRF Token again. Sounds Complex.. Not a problem
Suppose you reload the page & CodeIgniter sets the New CSRF Hash, you can use that to make a AjaxPOST request. But if don't make any request or reload the page, after that within 5 minutes, The old CSRF will be expired. Now if you call AjaxPOST request again, you get 500/403 error in your response. That means CodeIgniter expired the old CSRF hash because you hadn't made any request again during CSRF expiration time (5 minutes), and after that when you are sending an HTTP POST request with OLD CSRF Token & That is actually gone.... Clear :)
So, what we can do to get new CSRF token when making an AjaxPOST..?
- Well, for the GET request you do not need to send any CSRF token.
- But for the POST Yes! you have to send CSRF with in AjaxPOST if you are using CodeIgniter CSRF Security $config['csrf_protection'] = TRUE;
The logic behind is, get new CSRF hash before you making any AjaxPOST by using GET. Set it somewhere in DOM or attach in your AjaxSetup.
I am new in CodeIgniter .. :( Do you have any example..?
(Bulma!! Why you hit my Car again...) Yes Sure!!! :)
Here is View Html Code:
<!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./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>
Here is Controller:
<?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 */
Hope you enjoyed the answer & any suggestions, ments are much appreciated... as always .. :D
Thank you Neeraj! Your solution worked for me.
I used the following code for AJAX DataTable in CodeIgniter. This is to trigger your CSRF Refresh method upon getting results from DataTable's AJAX call.
$('#table').DataTable({
"ajax": {
"url": "<?php echo site_url(); ?>list",
"type": "POST",
"dataSrc": function ( json ) {
$(document).CsrfAjaxGet();
return json.data;
}
}
});
Please add this line in your page in script tag.
$(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
});
Let me know if it not works
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742390709a4434954.html
评论列表(0条)