我试图在CodeIgniter内执行Ajax调用。如前所述,当CSRF保护处于活动状态时,必须将散列(随机生成的)与每个请求一起提交给服务器。
在研究中,我发现以下代码总是通过Ajax请求与其他数据一起发送散列:
$.ajaxSetup({
data: {
arquivo_facil_tk: $.cookie('arquivo_facil_co')
}
});
所以我在页面加载后的第一次调用中得到了一个肯定的结果。但是要尝试第二次调用,会得到错误403。我还发现了为每次Ajax调用添加此代码片段的选项,但是由于我的软件执行了多次调用,因此它变得不可行且不礼貌。
我该如何解决这个问题?也尝试使用beforeend事件,但得到相同的错误
与其使用ajaxSetup
,不如在实际的AJAX调用中包括CSRF令牌和data
,如下所示:
data: {var: value, arquivo_facil_tk: $.cookie('arquivo_facil_co')}
或者如果你只是序列化表单:
data: $(this).serialize() + '&arquivo_facil_tk=' + $.cookie('arquivo_facil_co')
问题是csrf令牌只对一个调用有效,所以如果您想在不刷新页面的情况下对另一个post请求使用ajax,则需要在不重新加载表单的情况下以某种方式获得新的令牌。您可以在codeigniter控制器中通过将新令牌发送回请求脚本来完成此操作。
在CodeIgniter控制器中:
$data = array('data'=> 'data to send back to browser');
$csrf = $this->security->get_csrf_hash();
$this->output
->set_content_type('application/json')
->set_output(json_encode(array('data' => $data, 'csrf' => $csrf)));
$data =返回给浏览器的数据
$csrf =浏览器下一个ajax post请求使用的新的csrf令牌
显然你可以用其他方式输出,但JSON主要用于ajax调用。还可以在每个post响应中以这种方式包含令牌,以用于下一个post请求
然后在你的下一个ajax请求(javascript):
var token = data.csrf;
$.ajax({
url: '/next/ajax/request/url',
type: 'POST',
data: { new_data: 'new data to send via post', csrf_token:token },
cache: false,
success: function(data, textStatus, jqXHR) {
// Get new csrf token for next ajax post
var new_csrf_token = data.csrf
//Do something with data returned from post request
},
error: function(jqXHR, textStatus, errorThrown) {
// Handle errors here
console.log('ERRORS: ' + textStatus + ' - ' + errorThrown );
}
});
还请记住,我已经有csrf_token:token
取代crf_token
与您的令牌的名称在应用程序/config/config.php中找到,在线声明$config['csrf_token_name'] = 'csrf_token';
我也遇到了同样的问题。解决方案?我在整个系统中使用一个CSRF令牌,仅在登录/注销(以及类似的功能)时更改。
为了避免同一表单的多次提交(如双击甚至攻击),当我调用表单时,我还在事务表上插入一个随机ID。
当我收到这个表单时,我检查事务表中的ID。如果存在,执行操作并从事务表中删除ID。如果没有,显示消息错误