我正在对视频进行一个喜欢/不喜欢的ajax调用,我发现我需要在提交数据时传递CSRF令牌。
当用户点击"喜欢"时,我必须调用一个,当用户点击"不喜欢"时,我必须调用一个。我的问题是,如果用户点击喜欢,并意识到他们犯了一个错误,点击不喜欢,他们将收到一个错误:
403 Forbidden
The action you have requested is not allowed.
如果用户先刷新页面并更改其选择,则一切正常。只有当他们试图在不刷新的情况下从一个切换到另一个时才会出现这种情况。
下面是我的代码:<script>
// like btn
$('.like-btn').click(function() {
$('.dislike-btn').removeClass('text-danger');
$(this).addClass('liked-video');
$.ajax({
type:"POST",
url: '<?=base_url("videos/like_video")?>',
data: {video_id: <?=$video_id?>, user_id: <?=$logged_in_userid?>, value: "like", '<?=$this->security->get_csrf_token_name()?>':'<?=$this->security->get_csrf_hash()?>'},
success: function() {}
});
});
// dislike btn
$('.dislike-btn').click(function() {
$('.like-btn').removeClass('text-success');
$(this).addClass('disliked-video');
$.ajax({
type:"POST",
url: '<?=base_url("videos/dislike_video")?>',
data: {video_id: <?=$video_id?>, user_id: <?=$logged_in_userid?>, value: "dislike", '<?=$this->security->get_csrf_token_name()?>':'<?=$this->security->get_csrf_hash()?>'},
success: function() {}
});
});
</script>
为什么当用户改变他们的选择时,它会给用户一个错误?
所以我从用户指南中复制了这一段。
"令牌可以在每次提交时重新生成(默认),也可以在CSRF cookie的整个生命周期中保持不变。令牌的默认再生提供了更严格的安全性,但可能会导致可用性问题,因为其他令牌会失效(后退/前进导航、多个选项卡/窗口、异步操作等)。您可以通过编辑以下配置参数来更改此行为。"
尝试在你的配置文件中添加/编辑这一行:
$config['csrf_regeneration'] = TRUE;
还有另一种不需要禁用csrf再生的方法。您可以将新的CSRF令牌发送回调用ajax脚本。
在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';