【发布时间】:2016-12-30 15:36:47
【问题描述】:
您好,当使用 ajax 提交表单时,我正在寻找在 codeigniter 中重新生成 csrf 令牌的过程。我希望在不刷新页面的情况下重新生成令牌。有没有办法做到这一点。
【问题讨论】:
标签: codeigniter
您好,当使用 ajax 提交表单时,我正在寻找在 codeigniter 中重新生成 csrf 令牌的过程。我希望在不刷新页面的情况下重新生成令牌。有没有办法做到这一点。
【问题讨论】:
标签: codeigniter
对我有用的解决方案是,当为每个请求启用 CSRF 时,随后的 ajax 发布是在请求失败时在 AJAX Success 中发出 GET 请求,因为令牌已过期。然后有一个隐藏字段继续使用最新令牌进行更新,如果在发出请求时它已过期,您发出 GET REQUEST 以获取最新令牌,然后在提交表单或发出 POST 请求的函数上调用点击事件,这意味着该函数必须传递“this”或ID作为参数的一部分。这使得用户无法在后台实现更新令牌的过程
【讨论】:
根据情况,我在不同时间使用两种解决方案。
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'];?>" />
这是很重要的一点: 当然,在发送帖子数据后,您需要刷新令牌哈希值(在您的表单输入字段或 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 中没有异常,并在需要时重新加载令牌和哈希数据。这看起来很复杂,需要解释一下,但是一旦你完成了一次,就真的很容易在需要时一次又一次地做,而且你的网站比简单地避免使用其他选项的问题要安全得多。
【讨论】:
我发现使用 form helper 函数与 Codeigniter 一起使用效果更好 CSRF 并停止抛出 CSRF 错误如果您使用正常的 html 输入 会一直抛出 CSRF 错误。
这是一个 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 哈希数组。
【讨论】: