在提交Ajax时重新生成CRSF令牌codeigniter



嗨,我正在寻找当使用ajax提交表单时,在codeigniter中重新生成csrf令牌的过程。我希望在不刷新页面的情况下重新生成令牌。有办法做到这一点吗。

根据情况,我在不同的时间使用两种解决方案。

1.有点乱,但建议使用

在控制器中获取令牌名称和哈希值,并将其设置为页面上的某个位置的数据字段(无论您选择何处)。例如

// get the data and pass it to your view
$token_name = $this->security->get_csrf_token_name();
$token_hash = $this->security->get_csrf_hash();
// in your view file, load it into a div for instance
<div id="my_div" data-token="<?php echo $token_name; ?>" data-hash="<?php echo $token_name; ?>"

现在,在js-ajax代码中,您只需读取"my_div"中的数据值,就可以为ajax调用获取正确的数据。

如果你的页面上有一个真正的表单,这会变得更容易,在这种情况下,与其使用一些div,不如不要在表单上使用form_open,而是自己创建隐藏的表单字段,这样你就可以通过js轻松地阅读它。

<input type="hidden" id="my_data" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />

这是重要的一点:当然,在发送post数据后,您需要刷新令牌哈希值(在表单输入字段或div数据中,但您已经选择了刷新)。编写一个名为"refresh_csrf_data"的js函数,并使用"GET"获取数据和更新字段。然后,每当您完成ajax文章时,都可以调用此函数。

因此,每个ajax调用都读取令牌数据,执行调用,然后刷新令牌数据,为下一次调用做好准备。

2.简单但不太安全

或者,您可以使用为ajax调用禁用CSRF

$config['csrf_exclude_uris'] = array('controller/method');

CSRF设置的配置文件中。

3.更容易,但也不太安全,我不使用它最后,你可以在每次提交时关闭重新生成CSRF哈希

$config['csrf_regenerate'] = FALSE;

但是,要谨慎行事。这会让你面临某些类型的攻击。

最适合你的答案完全取决于页面的类型、使用情况,如果用户当时是否登录,是关键任务还是次要任务,是财务等。

没有什么是完全安全的,所以有时这是一种妥协。就我个人而言,我会在完全重新生成时使用CSRF,URI中没有例外,并在需要时重新加载令牌和哈希数据。这看起来很复杂,很难解释,但一旦你做了一次,无论何时需要,都很容易一次又一次地做,而且你的网站将比简单地避免其他选项的问题安全得多。

对我有效的解决方案是,当为每个请求启用CSRF时,对于后续的ajax帖子,当请求因令牌过期而失败时,在ajax Success中发出GET请求。然后有一个隐藏的字段,该字段将继续使用最新的令牌更新,如果在发出请求时它已经过期,则您将发出GET request以获取最新的token,然后在提交表单的函数上调用单击事件,或发出POST请求的函数,这意味着函数必须作为参数的一部分传递"this"或ID。这使得用户无法在后台中实现更新令牌的过程

我发现使用表单助手函数与Codeigniter配合使用效果更好CSRF并停止抛出CSRF错误如果您使用正常的html输入将不断抛出CSRF错误。

  • http://www.codeigniter.com/user_guide/helpers/form_helper.html#form_input
  • http://www.codeigniter.com/user_guide/helpers/form_helper.html#form_password

下面是一个AJAX 示例

<?php echo form_open('controller/example', array('id' => 'form-login'));?>
<?php 
$username_array = array(
'name' => 'username',
'id' => 'username',
'class' => ''
);
echo form_input($username_array);
?>
<?php 
$password_array = array(
'name' => 'password',
'id' => 'password',
'class' => ''
);
echo form_password($password_array);
?>
<?php 
$submit_array = array(
'name' => 'submit',
'id' => 'submit',
'class' => '',
'value' => 'Submit',
'type' => 'submit'
);
echo form_input($submit_array);
?>
<?php echo form_close();?>
<script type="text/javascript">
$('#submit').click(function(e){
e.preventDefault();
var post_data = {
'username' : $('#username').val(),
'password' : $('#password').val(),
'<?php echo $token_name; ?>' : '<?php echo $token_hash; ?>'
};
$.ajax
({ 
type: 'post',
url: "<?php echo base_url('example/');?>",
data: post_data,
dataType: 'json',
success: function(response)
{
if (response['success'] == true) {
// Success
} else {
// Error
}
}
});
}); 
</script>

示例

public function index() {
$data['token_name'] = $this->security->get_csrf_token_name();
$data['token_hash'] = $this->security->get_csrf_hash();
$this->load->view('login_view', $data);
}
public function example() {
$data = array('success' => false, 'messages' => array());
$this->form_validation->set_rules('username', 'username', 'required');
$this->form_validation->set_rules('password', 'password', 'required');
if ($this->form_validation->run() == false) {
foreach ($_POST as $key => $value) {
$data['messages'][$key] = form_error($key);
}
} else {

$data['success'] = true;
}
echo json_encode($data);
}

如果它不在会话中,那么您的控制器将像这个

public function save_date() // or whatever function you like
{
$regen_token = $this->security->get_csrf_hash();
$data = array(
"data" => $this->input->post('datas'),
);
$insert = $this->w_m->save($data);
echo json_encode(array("regen_token" => $regen_token));
}

在您的ajax中将显示如下:

$.ajax({
url: "your url",
type: "POST",
data: { your data },
dataType: "JSON",
success: function(data)
{
$("name or id of your csrf").val(JSON.stringify(data.regen_token)).trigger("change"); // this will be the function that every post you'll request and it automatically change the value of your csrf without refreshing the page.
},
error: function(errorThrown)
{
console.log(errorThrown);
}
});

在回调中添加一个csrf哈希数组。

最新更新